e0753a4f3b2a76a6050f9c2a3a836fac08ebd679
[android/platform/frameworks/opt/telephony.git] / src / 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.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.SharedPreferences;
24 import android.net.LinkProperties;
25 import android.net.NetworkCapabilities;
26 import android.net.wifi.WifiManager;
27 import android.os.AsyncResult;
28 import android.os.Build;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.Message;
32 import android.os.Registrant;
33 import android.os.RegistrantList;
34 import android.os.SystemProperties;
35 import android.preference.PreferenceManager;
36 import android.provider.Settings;
37 import android.telecom.VideoProfile;
38 import android.telephony.CellIdentityCdma;
39 import android.telephony.CellInfo;
40 import android.telephony.CellInfoCdma;
41 import android.telephony.DataConnectionRealTimeInfo;
42 import android.telephony.VoLteServiceState;
43 import android.telephony.Rlog;
44 import android.telephony.ServiceState;
45 import android.telephony.SignalStrength;
46 import android.telephony.SubscriptionManager;
47 import android.text.TextUtils;
48
49 import com.android.ims.ImsManager;
50 import com.android.internal.R;
51 import com.android.internal.telephony.dataconnection.DcTrackerBase;
52 import com.android.internal.telephony.imsphone.ImsPhone;
53 import com.android.internal.telephony.test.SimulatedRadioControl;
54 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
55 import com.android.internal.telephony.uicc.IccFileHandler;
56 import com.android.internal.telephony.uicc.IccRecords;
57 import com.android.internal.telephony.uicc.IsimRecords;
58 import com.android.internal.telephony.uicc.UiccCard;
59 import com.android.internal.telephony.uicc.UiccCardApplication;
60 import com.android.internal.telephony.uicc.UiccController;
61 import com.android.internal.telephony.uicc.UsimServiceTable;
62
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.util.ArrayList;
66 import java.util.List;
67 import java.util.Locale;
68 import java.util.concurrent.atomic.AtomicReference;
69
70 /**
71  * (<em>Not for SDK use</em>)
72  * A base implementation for the com.android.internal.telephony.Phone interface.
73  *
74  * Note that implementations of Phone.java are expected to be used
75  * from a single application thread. This should be the same thread that
76  * originally called PhoneFactory to obtain the interface.
77  *
78  *  {@hide}
79  *
80  */
81
82 public abstract class PhoneBase extends Handler implements Phone {
83     private static final String LOG_TAG = "PhoneBase";
84
85     private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
86         @Override
87         public void onReceive(Context context, Intent intent) {
88             // TODO: MSIM potentially replace SUBID with information available to external
89             // service, e.g. slot ID
90             if (intent.hasExtra(ImsManager.EXTRA_SUBID)) {
91                 if (intent.getLongExtra(ImsManager.EXTRA_SUBID, -1) != getSubId())
92                     return;
93             }
94
95             if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
96                 mImsServiceReady = true;
97                 updateImsPhone();
98             } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
99                 mImsServiceReady = false;
100                 updateImsPhone();
101             }
102         }
103     };
104
105     // Key used to read and write the saved network selection numeric value
106     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
107     // Key used to read and write the saved network selection operator name
108     public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
109
110
111     // Key used to read/write "disable data connection on boot" pref (used for testing)
112     public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
113
114     /* Event Constants */
115     protected static final int EVENT_RADIO_AVAILABLE             = 1;
116     /** Supplementary Service Notification received. */
117     protected static final int EVENT_SSN                         = 2;
118     protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
119     protected static final int EVENT_MMI_DONE                    = 4;
120     protected static final int EVENT_RADIO_ON                    = 5;
121     protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
122     protected static final int EVENT_USSD                        = 7;
123     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
124     protected static final int EVENT_GET_IMEI_DONE               = 9;
125     protected static final int EVENT_GET_IMEISV_DONE             = 10;
126     protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
127     protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
128     protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
129     protected static final int EVENT_CALL_RING                   = 14;
130     protected static final int EVENT_CALL_RING_CONTINUE          = 15;
131
132     // Used to intercept the carrier selection calls so that
133     // we can save the values.
134     protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
135     protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
136     protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
137     protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
138     protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
139     // Events for CDMA support
140     protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
141     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
142     protected static final int EVENT_NV_READY                       = 23;
143     protected static final int EVENT_SET_ENHANCED_VP                = 24;
144     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
145     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
146     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
147     // other
148     protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
149     protected static final int EVENT_ICC_RECORD_EVENTS              = 29;
150     protected static final int EVENT_ICC_CHANGED                    = 30;
151     // Single Radio Voice Call Continuity
152     protected static final int EVENT_SRVCC_STATE_CHANGED            = 31;
153     protected static final int EVENT_INITIATE_SILENT_REDIAL         = 32;
154     protected static final int EVENT_UNSOL_OEM_HOOK_RAW             = 33;
155     protected static final int EVENT_LAST                           = EVENT_UNSOL_OEM_HOOK_RAW;
156
157     // Key used to read/write current CLIR setting
158     public static final String CLIR_KEY = "clir_key";
159
160     // Key used for storing voice mail count
161     public static final String VM_COUNT = "vm_count_key";
162     // Key used to read/write the ID for storing the voice mail
163     public static final String VM_ID = "vm_id_key";
164
165     // Key used to read/write "disable DNS server check" pref (used for testing)
166     public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
167
168     /**
169      * Small container class used to hold information relevant to
170      * the carrier selection process. operatorNumeric can be ""
171      * if we are looking for automatic selection. operatorAlphaLong is the
172      * corresponding operator name.
173      */
174     protected static class NetworkSelectMessage {
175         public Message message;
176         public String operatorNumeric;
177         public String operatorAlphaLong;
178     }
179
180     /* Instance Variables */
181     public CommandsInterface mCi;
182     private int mVmCount = 0;
183     boolean mDnsCheckDisabled;
184     public DcTrackerBase mDcTracker;
185     boolean mDoesRilSendMultipleCallRing;
186     int mCallRingContinueToken;
187     int mCallRingDelay;
188     public boolean mIsTheCurrentActivePhone = true;
189     boolean mIsVoiceCapable = true;
190     protected UiccController mUiccController = null;
191     public AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
192     public SmsStorageMonitor mSmsStorageMonitor;
193     public SmsUsageMonitor mSmsUsageMonitor;
194     protected AtomicReference<UiccCardApplication> mUiccApplication =
195             new AtomicReference<UiccCardApplication>();
196
197     private TelephonyTester mTelephonyTester;
198     private final String mName;
199     private final String mActionDetached;
200     private final String mActionAttached;
201
202     // Holds the subscription information
203     protected Subscription mSubscriptionData = null;
204     protected int mPhoneId;
205
206     private final Object mImsLock = new Object();
207     private boolean mImsServiceReady = false;
208     protected ImsPhone mImsPhone = null;
209
210     @Override
211     public String getPhoneName() {
212         return mName;
213     }
214
215     /**
216      * Return the ActionDetached string. When this action is received by components
217      * they are to simulate detaching from the network.
218      *
219      * @return com.android.internal.telephony.{mName}.action_detached
220      *          {mName} is GSM, CDMA ...
221      */
222     public String getActionDetached() {
223         return mActionDetached;
224     }
225
226     /**
227      * Return the ActionAttached string. When this action is received by components
228      * they are to simulate attaching to the network.
229      *
230      * @return com.android.internal.telephony.{mName}.action_detached
231      *          {mName} is GSM, CDMA ...
232      */
233     public String getActionAttached() {
234         return mActionAttached;
235     }
236
237     /**
238      * Set a system property, unless we're in unit test mode
239      */
240     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
241     public void setSystemProperty(String property, String value) {
242         if(getUnitTestMode()) {
243             return;
244         }
245         SystemProperties.set(property, value);
246     }
247
248     /**
249      * Set a system property, unless we're in unit test mode
250      */
251     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
252     public String getSystemProperty(String property, String defValue) {
253         if(getUnitTestMode()) {
254             return null;
255         }
256         return SystemProperties.get(property, defValue);
257     }
258
259
260     protected final RegistrantList mPreciseCallStateRegistrants
261             = new RegistrantList();
262
263     protected final RegistrantList mHandoverRegistrants
264              = new RegistrantList();
265
266     protected final RegistrantList mNewRingingConnectionRegistrants
267             = new RegistrantList();
268
269     protected final RegistrantList mIncomingRingRegistrants
270             = new RegistrantList();
271
272     protected final RegistrantList mDisconnectRegistrants
273             = new RegistrantList();
274
275     protected final RegistrantList mServiceStateRegistrants
276             = new RegistrantList();
277
278     protected final RegistrantList mMmiCompleteRegistrants
279             = new RegistrantList();
280
281     protected final RegistrantList mMmiRegistrants
282             = new RegistrantList();
283
284     protected final RegistrantList mUnknownConnectionRegistrants
285             = new RegistrantList();
286
287     protected final RegistrantList mSuppServiceFailedRegistrants
288             = new RegistrantList();
289
290     protected final RegistrantList mSimRecordsLoadedRegistrants
291             = new RegistrantList();
292
293     protected Looper mLooper; /* to insure registrants are in correct thread*/
294
295     protected final Context mContext;
296
297     /**
298      * PhoneNotifier is an abstraction for all system-wide
299      * state change notification. DefaultPhoneNotifier is
300      * used here unless running we're inside a unit test.
301      */
302     protected PhoneNotifier mNotifier;
303
304     protected SimulatedRadioControl mSimulatedRadioControl;
305
306     boolean mUnitTestMode;
307
308     /**
309      * Constructs a PhoneBase in normal (non-unit test) mode.
310      *
311      * @param notifier An instance of DefaultPhoneNotifier,
312      * @param context Context object from hosting application
313      * unless unit testing.
314      * @param ci the CommandsInterface
315      */
316     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci) {
317         this(name, notifier, context, ci, false);
318     }
319
320     /**
321      * Constructs a PhoneBase in normal (non-unit test) mode.
322      *
323      * @param notifier An instance of DefaultPhoneNotifier,
324      * @param context Context object from hosting application
325      * unless unit testing.
326      * @param ci is CommandsInterface
327      * @param unitTestMode when true, prevents notifications
328      * of state change events
329      */
330     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
331             boolean unitTestMode) {
332         this(name, notifier, context, ci, unitTestMode, SubscriptionManager.DEFAULT_PHONE_ID);
333     }
334
335     /**
336      * Constructs a PhoneBase in normal (non-unit test) mode.
337      *
338      * @param notifier An instance of DefaultPhoneNotifier,
339      * @param context Context object from hosting application
340      * unless unit testing.
341      * @param ci is CommandsInterface
342      * @param unitTestMode when true, prevents notifications
343      * of state change events
344      * @param subscription is current phone subscription
345      */
346     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
347             boolean unitTestMode, int phoneId) {
348         mPhoneId = phoneId;
349         mName = name;
350         mNotifier = notifier;
351         mContext = context;
352         mLooper = Looper.myLooper();
353         mCi = ci;
354         mActionDetached = this.getClass().getPackage().getName() + ".action_detached";
355         mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
356
357         if (Build.IS_DEBUGGABLE) {
358             mTelephonyTester = new TelephonyTester(this);
359         }
360
361         setUnitTestMode(unitTestMode);
362
363         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
364         mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
365         mCi.setOnCallRing(this, EVENT_CALL_RING, null);
366
367         /* "Voice capable" means that this device supports circuit-switched
368         * (i.e. voice) phone calls over the telephony network, and is allowed
369         * to display the in-call UI while a cellular voice call is active.
370         * This will be false on "data only" devices which can't make voice
371         * calls and don't support any in-call UI.
372         */
373         mIsVoiceCapable = mContext.getResources().getBoolean(
374                 com.android.internal.R.bool.config_voice_capable);
375
376         /**
377          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
378          *  to be generated locally. Ideally all ring tones should be loops
379          * and this wouldn't be necessary. But to minimize changes to upper
380          * layers it is requested that it be generated by lower layers.
381          *
382          * By default old phones won't have the property set but do generate
383          * the RIL_UNSOL_CALL_RING so the default if there is no property is
384          * true.
385          */
386         mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
387                 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
388         Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
389
390         mCallRingDelay = SystemProperties.getInt(
391                 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
392         Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
393
394         if (getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) return;
395
396         setPropertiesByCarrier();
397
398         // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
399         mSmsStorageMonitor = new SmsStorageMonitor(this);
400         mSmsUsageMonitor = new SmsUsageMonitor(context);
401         mUiccController = UiccController.getInstance();
402         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
403
404         // Monitor IMS service
405         IntentFilter filter = new IntentFilter();
406         filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
407         filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
408         mContext.registerReceiver(mImsIntentReceiver, filter);
409
410         mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
411         mCi.setOnUnsolOemHookRaw(this, EVENT_UNSOL_OEM_HOOK_RAW, null);
412     }
413
414     @Override
415     public void dispose() {
416         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
417             mContext.unregisterReceiver(mImsIntentReceiver);
418             mCi.unSetOnCallRing(this);
419             // Must cleanup all connectionS and needs to use sendMessage!
420             mDcTracker.cleanUpAllConnections(null);
421             mIsTheCurrentActivePhone = false;
422             // Dispose the SMS usage and storage monitors
423             mSmsStorageMonitor.dispose();
424             mSmsUsageMonitor.dispose();
425             mUiccController.unregisterForIccChanged(this);
426             mCi.unregisterForSrvccStateChanged(this);
427             mCi.unSetOnUnsolOemHookRaw(this);
428
429             if (mTelephonyTester != null) {
430                 mTelephonyTester.dispose();
431             }
432
433             ImsPhone imsPhone = mImsPhone;
434             if (imsPhone != null) {
435                 imsPhone.unregisterForSilentRedial(this);
436                 imsPhone.dispose();
437             }
438         }
439     }
440
441     @Override
442     public void removeReferences() {
443         mSmsStorageMonitor = null;
444         mSmsUsageMonitor = null;
445         mIccRecords.set(null);
446         mUiccApplication.set(null);
447         mDcTracker = null;
448         mUiccController = null;
449
450         ImsPhone imsPhone = mImsPhone;
451         if (imsPhone != null) {
452             imsPhone.removeReferences();
453             mImsPhone = null;
454         }
455     }
456
457     /**
458      * When overridden the derived class needs to call
459      * super.handleMessage(msg) so this method has a
460      * a chance to process the message.
461      *
462      * @param msg
463      */
464     @Override
465     public void handleMessage(Message msg) {
466         AsyncResult ar;
467
468         if (!mIsTheCurrentActivePhone) {
469             Rlog.e(LOG_TAG, "Received message " + msg +
470                     "[" + msg.what + "] while being destroyed. Ignoring.");
471             return;
472         }
473         switch(msg.what) {
474             case EVENT_CALL_RING:
475                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
476                 ar = (AsyncResult)msg.obj;
477                 if (ar.exception == null) {
478                     PhoneConstants.State state = getState();
479                     if ((!mDoesRilSendMultipleCallRing)
480                             && ((state == PhoneConstants.State.RINGING) ||
481                                     (state == PhoneConstants.State.IDLE))) {
482                         mCallRingContinueToken += 1;
483                         sendIncomingCallRingNotification(mCallRingContinueToken);
484                     } else {
485                         notifyIncomingRing();
486                     }
487                 }
488                 break;
489
490             case EVENT_CALL_RING_CONTINUE:
491                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
492                 if (getState() == PhoneConstants.State.RINGING) {
493                     sendIncomingCallRingNotification(msg.arg1);
494                 }
495                 break;
496
497             case EVENT_ICC_CHANGED:
498                 onUpdateIccAvailability();
499                 break;
500
501             // handle the select network completion callbacks.
502             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
503             case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
504                 handleSetSelectNetwork((AsyncResult) msg.obj);
505                 break;
506
507             case EVENT_INITIATE_SILENT_REDIAL:
508                 Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
509                 ar = (AsyncResult) msg.obj;
510                 if ((ar.exception == null) && (ar.result != null)) {
511                     String dialString = (String) ar.result;
512                     if (TextUtils.isEmpty(dialString)) return;
513                     try {
514                         dialInternal(dialString, null, VideoProfile.VideoState.AUDIO_ONLY);
515                     } catch (CallStateException e) {
516                         Rlog.e(LOG_TAG, "silent redial failed: " + e);
517                     }
518                 }
519                 break;
520
521             case EVENT_SRVCC_STATE_CHANGED:
522                 ar = (AsyncResult)msg.obj;
523                 if (ar.exception == null) {
524                     handleSrvccStateChanged((int[]) ar.result);
525                 } else {
526                     Rlog.e(LOG_TAG, "Srvcc exception: " + ar.exception);
527                 }
528                 break;
529
530             case EVENT_UNSOL_OEM_HOOK_RAW:
531                 ar = (AsyncResult)msg.obj;
532                 if (ar.exception == null) {
533                     byte[] data = (byte[])ar.result;
534                     Rlog.d(LOG_TAG, "EVENT_UNSOL_OEM_HOOK_RAW data="
535                             + IccUtils.bytesToHexString(data));
536                     mNotifier.notifyOemHookRawEventForSubscriber(getSubId(), data);
537                 } else {
538                     Rlog.e(LOG_TAG, "OEM hook raw exception: " + ar.exception);
539                 }
540                 break;
541
542             default:
543                 throw new RuntimeException("unexpected event not handled");
544         }
545     }
546
547     private void handleSrvccStateChanged(int[] ret) {
548         Rlog.d(LOG_TAG, "handleSrvccStateChanged");
549
550         Connection conn = null;
551         ImsPhone imsPhone = mImsPhone;
552         Call.SrvccState srvccState = Call.SrvccState.NONE;
553         if (ret != null && ret.length != 0) {
554             int state = ret[0];
555             switch(state) {
556                 case VoLteServiceState.HANDOVER_STARTED:
557                     srvccState = Call.SrvccState.STARTED;
558                     if (imsPhone != null) {
559                         conn = imsPhone.getHandoverConnection();
560                     } else {
561                         Rlog.d(LOG_TAG, "HANDOVER_STARTED: mImsPhone null");
562                     }
563                     break;
564                 case VoLteServiceState.HANDOVER_COMPLETED:
565                     srvccState = Call.SrvccState.COMPLETED;
566                     if (imsPhone != null) {
567                         imsPhone.notifySrvccState(srvccState);
568                     } else {
569                         Rlog.d(LOG_TAG, "HANDOVER_COMPLETED: mImsPhone null");
570                     }
571                     break;
572                 case VoLteServiceState.HANDOVER_FAILED:
573                 case VoLteServiceState.HANDOVER_CANCELED:
574                     srvccState = Call.SrvccState.FAILED;
575                     break;
576
577                 default:
578                     //ignore invalid state
579                     return;
580             }
581
582             getCallTracker().notifySrvccState(srvccState, conn);
583
584             VoLteServiceState lteState = new VoLteServiceState(state);
585             notifyVoLteServiceStateChanged(lteState);
586         }
587     }
588
589     // Inherited documentation suffices.
590     @Override
591     public Context getContext() {
592         return mContext;
593     }
594
595     // Will be called when icc changed
596     protected abstract void onUpdateIccAvailability();
597
598     /**
599      * Disables the DNS check (i.e., allows "0.0.0.0").
600      * Useful for lab testing environment.
601      * @param b true disables the check, false enables.
602      */
603     @Override
604     public void disableDnsCheck(boolean b) {
605         mDnsCheckDisabled = b;
606         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
607         SharedPreferences.Editor editor = sp.edit();
608         editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
609         editor.apply();
610     }
611
612     /**
613      * Returns true if the DNS check is currently disabled.
614      */
615     @Override
616     public boolean isDnsCheckDisabled() {
617         return mDnsCheckDisabled;
618     }
619
620     // Inherited documentation suffices.
621     @Override
622     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
623         checkCorrectThread(h);
624
625         mPreciseCallStateRegistrants.addUnique(h, what, obj);
626     }
627
628     // Inherited documentation suffices.
629     @Override
630     public void unregisterForPreciseCallStateChanged(Handler h) {
631         mPreciseCallStateRegistrants.remove(h);
632     }
633
634     /**
635      * Subclasses of Phone probably want to replace this with a
636      * version scoped to their packages
637      */
638     protected void notifyPreciseCallStateChangedP() {
639         AsyncResult ar = new AsyncResult(null, this, null);
640         mPreciseCallStateRegistrants.notifyRegistrants(ar);
641
642         mNotifier.notifyPreciseCallState(this);
643     }
644
645     @Override
646     public void registerForHandoverStateChanged(Handler h, int what, Object obj) {
647         checkCorrectThread(h);
648         mHandoverRegistrants.addUnique(h, what, obj);
649     }
650
651     @Override
652     public void unregisterForHandoverStateChanged(Handler h) {
653         mHandoverRegistrants.remove(h);
654     }
655
656     /**
657      * Subclasses of Phone probably want to replace this with a
658      * version scoped to their packages
659      */
660     public void notifyHandoverStateChanged(Connection cn) {
661        AsyncResult ar = new AsyncResult(null, cn, null);
662        mHandoverRegistrants.notifyRegistrants(ar);
663     }
664
665     public void migrateFrom(PhoneBase from) {
666         migrate(mHandoverRegistrants, from.mHandoverRegistrants);
667         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
668         migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
669         migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
670         migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
671         migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
672         migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
673         migrate(mMmiRegistrants, from.mMmiRegistrants);
674         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
675         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
676     }
677
678     public void migrate(RegistrantList to, RegistrantList from) {
679         from.removeCleared();
680         for (int i = 0, n = from.size(); i < n; i++) {
681             to.add((Registrant) from.get(i));
682         }
683     }
684
685     // Inherited documentation suffices.
686     @Override
687     public void registerForUnknownConnection(Handler h, int what, Object obj) {
688         checkCorrectThread(h);
689
690         mUnknownConnectionRegistrants.addUnique(h, what, obj);
691     }
692
693     // Inherited documentation suffices.
694     @Override
695     public void unregisterForUnknownConnection(Handler h) {
696         mUnknownConnectionRegistrants.remove(h);
697     }
698
699     // Inherited documentation suffices.
700     @Override
701     public void registerForNewRingingConnection(
702             Handler h, int what, Object obj) {
703         checkCorrectThread(h);
704
705         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
706     }
707
708     // Inherited documentation suffices.
709     @Override
710     public void unregisterForNewRingingConnection(Handler h) {
711         mNewRingingConnectionRegistrants.remove(h);
712     }
713
714     // Inherited documentation suffices.
715     @Override
716     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
717         mCi.registerForInCallVoicePrivacyOn(h, what, obj);
718     }
719
720     // Inherited documentation suffices.
721     @Override
722     public void unregisterForInCallVoicePrivacyOn(Handler h){
723         mCi.unregisterForInCallVoicePrivacyOn(h);
724     }
725
726     // Inherited documentation suffices.
727     @Override
728     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
729         mCi.registerForInCallVoicePrivacyOff(h, what, obj);
730     }
731
732     // Inherited documentation suffices.
733     @Override
734     public void unregisterForInCallVoicePrivacyOff(Handler h){
735         mCi.unregisterForInCallVoicePrivacyOff(h);
736     }
737
738     // Inherited documentation suffices.
739     @Override
740     public void registerForIncomingRing(
741             Handler h, int what, Object obj) {
742         checkCorrectThread(h);
743
744         mIncomingRingRegistrants.addUnique(h, what, obj);
745     }
746
747     // Inherited documentation suffices.
748     @Override
749     public void unregisterForIncomingRing(Handler h) {
750         mIncomingRingRegistrants.remove(h);
751     }
752
753     // Inherited documentation suffices.
754     @Override
755     public void registerForDisconnect(Handler h, int what, Object obj) {
756         checkCorrectThread(h);
757
758         mDisconnectRegistrants.addUnique(h, what, obj);
759     }
760
761     // Inherited documentation suffices.
762     @Override
763     public void unregisterForDisconnect(Handler h) {
764         mDisconnectRegistrants.remove(h);
765     }
766
767     // Inherited documentation suffices.
768     @Override
769     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
770         checkCorrectThread(h);
771
772         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
773     }
774
775     // Inherited documentation suffices.
776     @Override
777     public void unregisterForSuppServiceFailed(Handler h) {
778         mSuppServiceFailedRegistrants.remove(h);
779     }
780
781     // Inherited documentation suffices.
782     @Override
783     public void registerForMmiInitiate(Handler h, int what, Object obj) {
784         checkCorrectThread(h);
785
786         mMmiRegistrants.addUnique(h, what, obj);
787     }
788
789     // Inherited documentation suffices.
790     @Override
791     public void unregisterForMmiInitiate(Handler h) {
792         mMmiRegistrants.remove(h);
793     }
794
795     // Inherited documentation suffices.
796     @Override
797     public void registerForMmiComplete(Handler h, int what, Object obj) {
798         checkCorrectThread(h);
799
800         mMmiCompleteRegistrants.addUnique(h, what, obj);
801     }
802
803     // Inherited documentation suffices.
804     @Override
805     public void unregisterForMmiComplete(Handler h) {
806         checkCorrectThread(h);
807
808         mMmiCompleteRegistrants.remove(h);
809     }
810
811     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
812         logUnexpectedCdmaMethodCall("registerForSimRecordsLoaded");
813     }
814
815     public void unregisterForSimRecordsLoaded(Handler h) {
816         logUnexpectedCdmaMethodCall("unregisterForSimRecordsLoaded");
817     }
818
819     @Override
820     public void setNetworkSelectionModeAutomatic(Message response) {
821         // wrap the response message in our own message along with
822         // an empty string (to indicate automatic selection) for the
823         // operator's id.
824         NetworkSelectMessage nsm = new NetworkSelectMessage();
825         nsm.message = response;
826         nsm.operatorNumeric = "";
827         nsm.operatorAlphaLong = "";
828
829         Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
830         mCi.setNetworkSelectionModeAutomatic(msg);
831     }
832
833     @Override
834     public void selectNetworkManually(OperatorInfo network, Message response) {
835         // wrap the response message in our own message along with
836         // the operator's id.
837         NetworkSelectMessage nsm = new NetworkSelectMessage();
838         nsm.message = response;
839         nsm.operatorNumeric = network.getOperatorNumeric();
840         nsm.operatorAlphaLong = network.getOperatorAlphaLong();
841
842         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
843         mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
844     }
845
846     /**
847      * Used to track the settings upon completion of the network change.
848      */
849     private void handleSetSelectNetwork(AsyncResult ar) {
850         // look for our wrapper within the asyncresult, skip the rest if it
851         // is null.
852         if (!(ar.userObj instanceof NetworkSelectMessage)) {
853             Rlog.e(LOG_TAG, "unexpected result from user object.");
854             return;
855         }
856
857         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
858
859         // found the object, now we send off the message we had originally
860         // attached to the request.
861         if (nsm.message != null) {
862             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
863             nsm.message.sendToTarget();
864         }
865
866         // open the shared preferences editor, and write the value.
867         // nsm.operatorNumeric is "" if we're in automatic.selection.
868         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
869         SharedPreferences.Editor editor = sp.edit();
870         editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
871         editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong);
872
873         // commit and log the result.
874         if (!editor.commit()) {
875             Rlog.e(LOG_TAG, "failed to commit network selection preference");
876         }
877     }
878
879     /**
880      * Method to retrieve the saved operator id from the Shared Preferences
881      */
882     private String getSavedNetworkSelection() {
883         // open the shared preferences and search with our key.
884         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
885         return sp.getString(NETWORK_SELECTION_KEY, "");
886     }
887
888     /**
889      * Method to restore the previously saved operator id, or reset to
890      * automatic selection, all depending upon the value in the shared
891      * preferences.
892      */
893     public void restoreSavedNetworkSelection(Message response) {
894         // retrieve the operator id
895         String networkSelection = getSavedNetworkSelection();
896
897         // set to auto if the id is empty, otherwise select the network.
898         if (TextUtils.isEmpty(networkSelection)) {
899             mCi.setNetworkSelectionModeAutomatic(response);
900         } else {
901             mCi.setNetworkSelectionModeManual(networkSelection, response);
902         }
903     }
904
905     // Inherited documentation suffices.
906     @Override
907     public void setUnitTestMode(boolean f) {
908         mUnitTestMode = f;
909     }
910
911     // Inherited documentation suffices.
912     @Override
913     public boolean getUnitTestMode() {
914         return mUnitTestMode;
915     }
916
917     /**
918      * To be invoked when a voice call Connection disconnects.
919      *
920      * Subclasses of Phone probably want to replace this with a
921      * version scoped to their packages
922      */
923     protected void notifyDisconnectP(Connection cn) {
924         AsyncResult ar = new AsyncResult(null, cn, null);
925         mDisconnectRegistrants.notifyRegistrants(ar);
926     }
927
928     // Inherited documentation suffices.
929     @Override
930     public void registerForServiceStateChanged(
931             Handler h, int what, Object obj) {
932         checkCorrectThread(h);
933
934         mServiceStateRegistrants.add(h, what, obj);
935     }
936
937     // Inherited documentation suffices.
938     @Override
939     public void unregisterForServiceStateChanged(Handler h) {
940         mServiceStateRegistrants.remove(h);
941     }
942
943     // Inherited documentation suffices.
944     @Override
945     public void registerForRingbackTone(Handler h, int what, Object obj) {
946         mCi.registerForRingbackTone(h, what, obj);
947     }
948
949     // Inherited documentation suffices.
950     @Override
951     public void unregisterForRingbackTone(Handler h) {
952         mCi.unregisterForRingbackTone(h);
953     }
954
955     // Inherited documentation suffices.
956     @Override
957     public void registerForOnHoldTone(Handler h, int what, Object obj) {
958     }
959
960     // Inherited documentation suffices.
961     @Override
962     public void unregisterForOnHoldTone(Handler h) {
963     }
964
965     // Inherited documentation suffices.
966     @Override
967     public void registerForResendIncallMute(Handler h, int what, Object obj) {
968         mCi.registerForResendIncallMute(h, what, obj);
969     }
970
971     // Inherited documentation suffices.
972     @Override
973     public void unregisterForResendIncallMute(Handler h) {
974         mCi.unregisterForResendIncallMute(h);
975     }
976
977     @Override
978     public void setEchoSuppressionEnabled() {
979         // no need for regular phone
980     }
981
982     /**
983      * Subclasses of Phone probably want to replace this with a
984      * version scoped to their packages
985      */
986     protected void notifyServiceStateChangedP(ServiceState ss) {
987         AsyncResult ar = new AsyncResult(null, ss, null);
988         mServiceStateRegistrants.notifyRegistrants(ar);
989
990         mNotifier.notifyServiceState(this);
991     }
992
993     // Inherited documentation suffices.
994     @Override
995     public SimulatedRadioControl getSimulatedRadioControl() {
996         return mSimulatedRadioControl;
997     }
998
999     /**
1000      * Verifies the current thread is the same as the thread originally
1001      * used in the initialization of this instance. Throws RuntimeException
1002      * if not.
1003      *
1004      * @exception RuntimeException if the current thread is not
1005      * the thread that originally obtained this PhoneBase instance.
1006      */
1007     private void checkCorrectThread(Handler h) {
1008         if (h.getLooper() != mLooper) {
1009             throw new RuntimeException(
1010                     "com.android.internal.telephony.Phone must be used from within one thread");
1011         }
1012     }
1013
1014     /**
1015      * Set the properties by matching the carrier string in
1016      * a string-array resource
1017      */
1018     private void setPropertiesByCarrier() {
1019         String carrier = SystemProperties.get("ro.carrier");
1020
1021         if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
1022             return;
1023         }
1024
1025         CharSequence[] carrierLocales = mContext.
1026                 getResources().getTextArray(R.array.carrier_properties);
1027
1028         for (int i = 0; i < carrierLocales.length; i+=3) {
1029             String c = carrierLocales[i].toString();
1030             if (carrier.equals(c)) {
1031                 final Locale l = Locale.forLanguageTag(carrierLocales[i + 1].toString().replace('_', '-'));
1032                 final String country = l.getCountry();
1033                 MccTable.setSystemLocale(mContext, l.getLanguage(), country);
1034
1035                 if (!country.isEmpty()) {
1036                     try {
1037                         Settings.Global.getInt(mContext.getContentResolver(),
1038                                 Settings.Global.WIFI_COUNTRY_CODE);
1039                     } catch (Settings.SettingNotFoundException e) {
1040                         // note this is not persisting
1041                         WifiManager wM = (WifiManager)
1042                                 mContext.getSystemService(Context.WIFI_SERVICE);
1043                         wM.setCountryCode(country, false);
1044                     }
1045                 }
1046                 return;
1047             }
1048         }
1049     }
1050
1051     /**
1052      * Get state
1053      */
1054     @Override
1055     public abstract PhoneConstants.State getState();
1056
1057     /**
1058      * Retrieves the IccFileHandler of the Phone instance
1059      */
1060     public IccFileHandler getIccFileHandler(){
1061         UiccCardApplication uiccApplication = mUiccApplication.get();
1062         IccFileHandler fh;
1063
1064         if (uiccApplication == null) {
1065             Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
1066             fh = null;
1067         } else {
1068             fh = uiccApplication.getIccFileHandler();
1069         }
1070
1071         Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
1072         return fh;
1073     }
1074
1075     /*
1076      * Retrieves the Handler of the Phone instance
1077      */
1078     public Handler getHandler() {
1079         return this;
1080     }
1081
1082     @Override
1083     public void updatePhoneObject(int voiceRadioTech) {
1084         // Only the PhoneProxy can update the phone object.
1085         PhoneFactory.getDefaultPhone().updatePhoneObject(voiceRadioTech);
1086     }
1087
1088     /**
1089     * Retrieves the ServiceStateTracker of the phone instance.
1090     */
1091     public ServiceStateTracker getServiceStateTracker() {
1092         return null;
1093     }
1094
1095     /**
1096     * Get call tracker
1097     */
1098     public CallTracker getCallTracker() {
1099         return null;
1100     }
1101
1102     public AppType getCurrentUiccAppType() {
1103         UiccCardApplication currentApp = mUiccApplication.get();
1104         if (currentApp != null) {
1105             return currentApp.getType();
1106         }
1107         return AppType.APPTYPE_UNKNOWN;
1108     }
1109
1110     @Override
1111     public IccCard getIccCard() {
1112         return null;
1113         //throw new Exception("getIccCard Shouldn't be called from PhoneBase");
1114     }
1115
1116     @Override
1117     public String getIccSerialNumber() {
1118         IccRecords r = mIccRecords.get();
1119         return (r != null) ? r.getIccId() : null;
1120     }
1121
1122     @Override
1123     public boolean getIccRecordsLoaded() {
1124         IccRecords r = mIccRecords.get();
1125         return (r != null) ? r.getRecordsLoaded() : false;
1126     }
1127
1128     /**
1129      * @return all available cell information or null if none.
1130      */
1131     @Override
1132     public List<CellInfo> getAllCellInfo() {
1133         List<CellInfo> cellInfoList = getServiceStateTracker().getAllCellInfo();
1134         return privatizeCellInfoList(cellInfoList);
1135     }
1136
1137     /**
1138      * Clear CDMA base station lat/long values if location setting is disabled.
1139      * @param cellInfoList the original cell info list from the RIL
1140      * @return the original list with CDMA lat/long cleared if necessary
1141      */
1142     private List<CellInfo> privatizeCellInfoList(List<CellInfo> cellInfoList) {
1143         int mode = Settings.Secure.getInt(getContext().getContentResolver(),
1144                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
1145         if (mode == Settings.Secure.LOCATION_MODE_OFF) {
1146             ArrayList<CellInfo> privateCellInfoList = new ArrayList<CellInfo>(cellInfoList.size());
1147             // clear lat/lon values for location privacy
1148             for (CellInfo c : cellInfoList) {
1149                 if (c instanceof CellInfoCdma) {
1150                     CellInfoCdma cellInfoCdma = (CellInfoCdma) c;
1151                     CellIdentityCdma cellIdentity = cellInfoCdma.getCellIdentity();
1152                     CellIdentityCdma maskedCellIdentity = new CellIdentityCdma(
1153                             cellIdentity.getNetworkId(),
1154                             cellIdentity.getSystemId(),
1155                             cellIdentity.getBasestationId(),
1156                             Integer.MAX_VALUE, Integer.MAX_VALUE);
1157                     CellInfoCdma privateCellInfoCdma = new CellInfoCdma(cellInfoCdma);
1158                     privateCellInfoCdma.setCellIdentity(maskedCellIdentity);
1159                     privateCellInfoList.add(privateCellInfoCdma);
1160                 } else {
1161                     privateCellInfoList.add(c);
1162                 }
1163             }
1164             cellInfoList = privateCellInfoList;
1165         }
1166         return cellInfoList;
1167     }
1168
1169     /**
1170      * {@inheritDoc}
1171      */
1172     @Override
1173     public void setCellInfoListRate(int rateInMillis) {
1174         mCi.setCellInfoListRate(rateInMillis, null);
1175     }
1176
1177     @Override
1178     /** @return true if there are messages waiting, false otherwise. */
1179     public boolean getMessageWaitingIndicator() {
1180         return mVmCount != 0;
1181     }
1182
1183     @Override
1184     public boolean getCallForwardingIndicator() {
1185         IccRecords r = mIccRecords.get();
1186         return (r != null) ? r.getVoiceCallForwardingFlag() : false;
1187     }
1188
1189     /**
1190      *  Query the status of the CDMA roaming preference
1191      */
1192     @Override
1193     public void queryCdmaRoamingPreference(Message response) {
1194         mCi.queryCdmaRoamingPreference(response);
1195     }
1196
1197     /**
1198      * Get the signal strength
1199      */
1200     @Override
1201     public SignalStrength getSignalStrength() {
1202         ServiceStateTracker sst = getServiceStateTracker();
1203         if (sst == null) {
1204             return new SignalStrength();
1205         } else {
1206             return sst.getSignalStrength();
1207         }
1208     }
1209
1210     /**
1211      *  Set the status of the CDMA roaming preference
1212      */
1213     @Override
1214     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
1215         mCi.setCdmaRoamingPreference(cdmaRoamingType, response);
1216     }
1217
1218     /**
1219      *  Set the status of the CDMA subscription mode
1220      */
1221     @Override
1222     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
1223         mCi.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
1224     }
1225
1226     /**
1227      *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
1228      */
1229     @Override
1230     public void setPreferredNetworkType(int networkType, Message response) {
1231         mCi.setPreferredNetworkType(networkType, response);
1232     }
1233
1234     @Override
1235     public void getPreferredNetworkType(Message response) {
1236         mCi.getPreferredNetworkType(response);
1237     }
1238
1239     @Override
1240     public void getSmscAddress(Message result) {
1241         mCi.getSmscAddress(result);
1242     }
1243
1244     @Override
1245     public void setSmscAddress(String address, Message result) {
1246         mCi.setSmscAddress(address, result);
1247     }
1248
1249     @Override
1250     public void setTTYMode(int ttyMode, Message onComplete) {
1251         mCi.setTTYMode(ttyMode, onComplete);
1252     }
1253
1254     @Override
1255     public void queryTTYMode(Message onComplete) {
1256         mCi.queryTTYMode(onComplete);
1257     }
1258
1259     @Override
1260     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
1261         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1262         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
1263     }
1264
1265     @Override
1266     public void getEnhancedVoicePrivacy(Message onComplete) {
1267         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1268         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
1269     }
1270
1271     @Override
1272     public void setBandMode(int bandMode, Message response) {
1273         mCi.setBandMode(bandMode, response);
1274     }
1275
1276     @Override
1277     public void queryAvailableBandMode(Message response) {
1278         mCi.queryAvailableBandMode(response);
1279     }
1280
1281     @Override
1282     public void invokeOemRilRequestRaw(byte[] data, Message response) {
1283         mCi.invokeOemRilRequestRaw(data, response);
1284     }
1285
1286     @Override
1287     public void invokeOemRilRequestStrings(String[] strings, Message response) {
1288         mCi.invokeOemRilRequestStrings(strings, response);
1289     }
1290
1291     @Override
1292     public void nvReadItem(int itemID, Message response) {
1293         mCi.nvReadItem(itemID, response);
1294     }
1295
1296     @Override
1297     public void nvWriteItem(int itemID, String itemValue, Message response) {
1298         mCi.nvWriteItem(itemID, itemValue, response);
1299     }
1300
1301     @Override
1302     public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
1303         mCi.nvWriteCdmaPrl(preferredRoamingList, response);
1304     }
1305
1306     @Override
1307     public void nvResetConfig(int resetType, Message response) {
1308         mCi.nvResetConfig(resetType, response);
1309     }
1310
1311     @Override
1312     public void notifyDataActivity() {
1313         mNotifier.notifyDataActivity(this);
1314     }
1315
1316     public void notifyMessageWaitingIndicator() {
1317         // Do not notify voice mail waiting if device doesn't support voice
1318         if (!mIsVoiceCapable)
1319             return;
1320
1321         // This function is added to send the notification to DefaultPhoneNotifier.
1322         mNotifier.notifyMessageWaitingChanged(this);
1323     }
1324
1325     public void notifyDataConnection(String reason, String apnType,
1326             PhoneConstants.DataState state) {
1327         mNotifier.notifyDataConnection(this, reason, apnType, state);
1328     }
1329
1330     public void notifyDataConnection(String reason, String apnType) {
1331         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
1332     }
1333
1334     public void notifyDataConnection(String reason) {
1335         String types[] = getActiveApnTypes();
1336         for (String apnType : types) {
1337             mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
1338         }
1339     }
1340
1341     public void notifyOtaspChanged(int otaspMode) {
1342         mNotifier.notifyOtaspChanged(this, otaspMode);
1343     }
1344
1345     public void notifySignalStrength() {
1346         mNotifier.notifySignalStrength(this);
1347     }
1348
1349     public void notifyCellInfo(List<CellInfo> cellInfo) {
1350         mNotifier.notifyCellInfo(this, privatizeCellInfoList(cellInfo));
1351     }
1352
1353     public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
1354         mNotifier.notifyDataConnectionRealTimeInfo(this, dcRtInfo);
1355     }
1356
1357     public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
1358         mNotifier.notifyVoLteServiceStateChanged(this, lteState);
1359     }
1360
1361     /**
1362      * @return true if a mobile originating emergency call is active
1363      */
1364     public boolean isInEmergencyCall() {
1365         return false;
1366     }
1367
1368     /**
1369      * @return true if we are in the emergency call back mode. This is a period where
1370      * the phone should be using as little power as possible and be ready to receive an
1371      * incoming call from the emergency operator.
1372      */
1373     public boolean isInEcm() {
1374         return false;
1375     }
1376
1377     @Override
1378     public abstract int getPhoneType();
1379
1380     /** @hide */
1381     /** @return number of voicemails */
1382     @Override
1383     public int getVoiceMessageCount(){
1384         return mVmCount;
1385     }
1386
1387     /** sets the voice mail count of the phone and notifies listeners. */
1388     public void setVoiceMessageCount(int countWaiting) {
1389         mVmCount = countWaiting;
1390         // notify listeners of voice mail
1391         notifyMessageWaitingIndicator();
1392     }
1393
1394     /** gets the voice mail count from preferences */
1395     protected int getStoredVoiceMessageCount() {
1396         int countVoiceMessages = 0;
1397         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
1398         String subscriberId = sp.getString(VM_ID, null);
1399         String currentSubscriberId = getSubscriberId();
1400
1401         Rlog.d(LOG_TAG, "Voicemail count retrieval for subscriberId = " + subscriberId +
1402                 " current subscriberId = " + currentSubscriberId);
1403
1404         if ((subscriberId != null) && (currentSubscriberId != null)
1405                 && (currentSubscriberId.equals(subscriberId))) {
1406             // get voice mail count from preferences
1407             countVoiceMessages = sp.getInt(VM_COUNT, 0);
1408             Rlog.d(LOG_TAG, "Voice Mail Count from preference = " + countVoiceMessages);
1409         }
1410         return countVoiceMessages;
1411     }
1412
1413     /**
1414      * Returns the CDMA ERI icon index to display
1415      */
1416     @Override
1417     public int getCdmaEriIconIndex() {
1418         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
1419         return -1;
1420     }
1421
1422     /**
1423      * Returns the CDMA ERI icon mode,
1424      * 0 - ON
1425      * 1 - FLASHING
1426      */
1427     @Override
1428     public int getCdmaEriIconMode() {
1429         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
1430         return -1;
1431     }
1432
1433     /**
1434      * Returns the CDMA ERI text,
1435      */
1436     @Override
1437     public String getCdmaEriText() {
1438         logUnexpectedCdmaMethodCall("getCdmaEriText");
1439         return "GSM nw, no ERI";
1440     }
1441
1442     @Override
1443     public String getCdmaMin() {
1444         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1445         logUnexpectedCdmaMethodCall("getCdmaMin");
1446         return null;
1447     }
1448
1449     @Override
1450     public boolean isMinInfoReady() {
1451         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1452         logUnexpectedCdmaMethodCall("isMinInfoReady");
1453         return false;
1454     }
1455
1456     @Override
1457     public String getCdmaPrlVersion(){
1458         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1459         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
1460         return null;
1461     }
1462
1463     @Override
1464     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1465         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1466         logUnexpectedCdmaMethodCall("sendBurstDtmf");
1467     }
1468
1469     @Override
1470     public void exitEmergencyCallbackMode() {
1471         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1472         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
1473     }
1474
1475     @Override
1476     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
1477         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1478         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
1479     }
1480
1481     @Override
1482     public void unregisterForCdmaOtaStatusChange(Handler h) {
1483         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1484         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
1485     }
1486
1487     @Override
1488     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
1489         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1490         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
1491     }
1492
1493     @Override
1494     public void unregisterForSubscriptionInfoReady(Handler h) {
1495         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1496         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
1497     }
1498
1499     /**
1500      * Returns true if OTA Service Provisioning needs to be performed.
1501      * If not overridden return false.
1502      */
1503     @Override
1504     public boolean needsOtaServiceProvisioning() {
1505         return false;
1506     }
1507
1508     /**
1509      * Return true if number is an OTASP number.
1510      * If not overridden return false.
1511      */
1512     @Override
1513     public  boolean isOtaSpNumber(String dialStr) {
1514         return false;
1515     }
1516
1517     @Override
1518     public void registerForCallWaiting(Handler h, int what, Object obj){
1519         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1520         logUnexpectedCdmaMethodCall("registerForCallWaiting");
1521     }
1522
1523     @Override
1524     public void unregisterForCallWaiting(Handler h){
1525         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1526         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
1527     }
1528
1529     @Override
1530     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
1531         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1532         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
1533     }
1534
1535     @Override
1536     public void unregisterForEcmTimerReset(Handler h) {
1537         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1538         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
1539     }
1540
1541     @Override
1542     public void registerForSignalInfo(Handler h, int what, Object obj) {
1543         mCi.registerForSignalInfo(h, what, obj);
1544     }
1545
1546     @Override
1547     public void unregisterForSignalInfo(Handler h) {
1548         mCi.unregisterForSignalInfo(h);
1549     }
1550
1551     @Override
1552     public void registerForDisplayInfo(Handler h, int what, Object obj) {
1553         mCi.registerForDisplayInfo(h, what, obj);
1554     }
1555
1556      @Override
1557     public void unregisterForDisplayInfo(Handler h) {
1558          mCi.unregisterForDisplayInfo(h);
1559      }
1560
1561     @Override
1562     public void registerForNumberInfo(Handler h, int what, Object obj) {
1563         mCi.registerForNumberInfo(h, what, obj);
1564     }
1565
1566     @Override
1567     public void unregisterForNumberInfo(Handler h) {
1568         mCi.unregisterForNumberInfo(h);
1569     }
1570
1571     @Override
1572     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
1573         mCi.registerForRedirectedNumberInfo(h, what, obj);
1574     }
1575
1576     @Override
1577     public void unregisterForRedirectedNumberInfo(Handler h) {
1578         mCi.unregisterForRedirectedNumberInfo(h);
1579     }
1580
1581     @Override
1582     public void registerForLineControlInfo(Handler h, int what, Object obj) {
1583         mCi.registerForLineControlInfo( h, what, obj);
1584     }
1585
1586     @Override
1587     public void unregisterForLineControlInfo(Handler h) {
1588         mCi.unregisterForLineControlInfo(h);
1589     }
1590
1591     @Override
1592     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
1593         mCi.registerFoT53ClirlInfo(h, what, obj);
1594     }
1595
1596     @Override
1597     public void unregisterForT53ClirInfo(Handler h) {
1598         mCi.unregisterForT53ClirInfo(h);
1599     }
1600
1601     @Override
1602     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
1603         mCi.registerForT53AudioControlInfo( h, what, obj);
1604     }
1605
1606     @Override
1607     public void unregisterForT53AudioControlInfo(Handler h) {
1608         mCi.unregisterForT53AudioControlInfo(h);
1609     }
1610
1611      @Override
1612     public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
1613          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1614          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
1615      }
1616
1617      @Override
1618     public void unsetOnEcbModeExitResponse(Handler h){
1619         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1620          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
1621      }
1622
1623     @Override
1624     public String[] getActiveApnTypes() {
1625         return mDcTracker.getActiveApnTypes();
1626     }
1627
1628     @Override
1629     public String getActiveApnHost(String apnType) {
1630         return mDcTracker.getActiveApnString(apnType);
1631     }
1632
1633     @Override
1634     public LinkProperties getLinkProperties(String apnType) {
1635         return mDcTracker.getLinkProperties(apnType);
1636     }
1637
1638     @Override
1639     public NetworkCapabilities getNetworkCapabilities(String apnType) {
1640         return mDcTracker.getNetworkCapabilities(apnType);
1641     }
1642
1643     @Override
1644     public boolean isDataConnectivityPossible() {
1645         return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
1646     }
1647
1648     @Override
1649     public boolean isDataConnectivityPossible(String apnType) {
1650         return ((mDcTracker != null) &&
1651                 (mDcTracker.isDataPossible(apnType)));
1652     }
1653
1654     /**
1655      * Notify registrants of a new ringing Connection.
1656      * Subclasses of Phone probably want to replace this with a
1657      * version scoped to their packages
1658      */
1659     public void notifyNewRingingConnectionP(Connection cn) {
1660         if (!mIsVoiceCapable)
1661             return;
1662         AsyncResult ar = new AsyncResult(null, cn, null);
1663         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
1664     }
1665
1666     /**
1667      * Notify registrants of a RING event.
1668      */
1669     private void notifyIncomingRing() {
1670         if (!mIsVoiceCapable)
1671             return;
1672         AsyncResult ar = new AsyncResult(null, this, null);
1673         mIncomingRingRegistrants.notifyRegistrants(ar);
1674     }
1675
1676     /**
1677      * Send the incoming call Ring notification if conditions are right.
1678      */
1679     private void sendIncomingCallRingNotification(int token) {
1680         if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
1681                 (token == mCallRingContinueToken)) {
1682             Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
1683             notifyIncomingRing();
1684             sendMessageDelayed(
1685                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
1686         } else {
1687             Rlog.d(LOG_TAG, "Ignoring ring notification request,"
1688                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
1689                     + " token=" + token
1690                     + " mCallRingContinueToken=" + mCallRingContinueToken
1691                     + " mIsVoiceCapable=" + mIsVoiceCapable);
1692         }
1693     }
1694
1695     @Override
1696     public boolean isCspPlmnEnabled() {
1697         // This function should be overridden by the class GSMPhone.
1698         // Not implemented in CDMAPhone.
1699         logUnexpectedGsmMethodCall("isCspPlmnEnabled");
1700         return false;
1701     }
1702
1703     @Override
1704     public IsimRecords getIsimRecords() {
1705         Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
1706         return null;
1707     }
1708
1709     @Override
1710     public String getMsisdn() {
1711         logUnexpectedGsmMethodCall("getMsisdn");
1712         return null;
1713     }
1714
1715     /**
1716      * Common error logger method for unexpected calls to CDMA-only methods.
1717      */
1718     private static void logUnexpectedCdmaMethodCall(String name)
1719     {
1720         Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1721                 "called, CDMAPhone inactive.");
1722     }
1723
1724     @Override
1725     public PhoneConstants.DataState getDataConnectionState() {
1726         return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
1727     }
1728
1729     /**
1730      * Common error logger method for unexpected calls to GSM/WCDMA-only methods.
1731      */
1732     private static void logUnexpectedGsmMethodCall(String name) {
1733         Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1734                 "called, GSMPhone inactive.");
1735     }
1736
1737     // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
1738     public void notifyCallForwardingIndicator() {
1739         // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
1740         Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
1741     }
1742
1743     public void notifyDataConnectionFailed(String reason, String apnType) {
1744         mNotifier.notifyDataConnectionFailed(this, reason, apnType);
1745     }
1746
1747     public void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
1748             String failCause) {
1749         mNotifier.notifyPreciseDataConnectionFailed(this, reason, apnType, apn, failCause);
1750     }
1751
1752     /**
1753      * {@inheritDoc}
1754      */
1755     @Override
1756     public int getLteOnCdmaMode() {
1757         return mCi.getLteOnCdmaMode();
1758     }
1759
1760     public void setVoiceMessageWaiting(int line, int countWaiting) {
1761         // This function should be overridden by class GSMPhone and CDMAPhone.
1762         Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
1763     }
1764
1765     /**
1766      * Gets the USIM service table from the UICC, if present and available.
1767      * @return an interface to the UsimServiceTable record, or null if not available
1768      */
1769     @Override
1770     public UsimServiceTable getUsimServiceTable() {
1771         IccRecords r = mIccRecords.get();
1772         return (r != null) ? r.getUsimServiceTable() : null;
1773     }
1774
1775     /**
1776      * Gets the Uicc card corresponding to this phone.
1777      * @return the UiccCard object corresponding to the phone ID.
1778      */
1779     @Override
1780     public UiccCard getUiccCard() {
1781         return mUiccController.getUiccCard(mPhoneId);
1782     }
1783
1784     /**
1785      * Get P-CSCF address from PCO after data connection is established or modified.
1786      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
1787      */
1788     @Override
1789     public String[] getPcscfAddress(String apnType) {
1790         return mDcTracker.getPcscfAddress(apnType);
1791     }
1792
1793     /**
1794      * Set IMS registration state
1795      */
1796     @Override
1797     public void setImsRegistrationState(boolean registered) {
1798         mDcTracker.setImsRegistrationState(registered);
1799     }
1800
1801     /**
1802      * Return an instance of a IMS phone
1803      */
1804     @Override
1805     public Phone getImsPhone() {
1806         return mImsPhone;
1807     }
1808
1809     @Override
1810     public ImsPhone relinquishOwnershipOfImsPhone() {
1811         synchronized (mImsLock) {
1812             if (mImsPhone == null)
1813                 return null;
1814
1815             ImsPhone imsPhone = mImsPhone;
1816             mImsPhone = null;
1817
1818             CallManager.getInstance().unregisterPhone(imsPhone);
1819             imsPhone.unregisterForSilentRedial(this);
1820
1821             return imsPhone;
1822         }
1823     }
1824
1825     @Override
1826     public void acquireOwnershipOfImsPhone(ImsPhone imsPhone) {
1827         synchronized (mImsLock) {
1828             if (imsPhone == null)
1829                 return;
1830
1831             if (mImsPhone != null) {
1832                 Rlog.e(LOG_TAG, "acquireOwnershipOfImsPhone: non-null mImsPhone." +
1833                         " Shouldn't happen - but disposing");
1834                 mImsPhone.dispose();
1835                 // Potential GC issue if someone keeps a reference to ImsPhone.
1836                 // However: this change will make sure that such a reference does
1837                 // not access functions through NULL pointer.
1838                 //mImsPhone.removeReferences();
1839             }
1840
1841             mImsPhone = imsPhone;
1842
1843             mImsServiceReady = true;
1844             mImsPhone.updateParentPhone(this);
1845             CallManager.getInstance().registerPhone(mImsPhone);
1846             mImsPhone.registerForSilentRedial(
1847                     this, EVENT_INITIATE_SILENT_REDIAL, null);
1848         }
1849     }
1850
1851     protected void updateImsPhone() {
1852         synchronized (mImsLock) {
1853             Rlog.d(LOG_TAG, "updateImsPhone"
1854                     + " mImsServiceReady=" + mImsServiceReady);
1855
1856             if (mImsServiceReady && (mImsPhone == null)) {
1857                 mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
1858                 CallManager.getInstance().registerPhone(mImsPhone);
1859                 mImsPhone.registerForSilentRedial(
1860                         this, EVENT_INITIATE_SILENT_REDIAL, null);
1861             } else if (!mImsServiceReady && (mImsPhone != null)) {
1862                 CallManager.getInstance().unregisterPhone(mImsPhone);
1863                 mImsPhone.unregisterForSilentRedial(this);
1864
1865                 mImsPhone.dispose();
1866                 // Potential GC issue if someone keeps a reference to ImsPhone.
1867                 // However: this change will make sure that such a reference does
1868                 // not access functions through NULL pointer.
1869                 //mImsPhone.removeReferences();
1870                 mImsPhone = null;
1871             }
1872         }
1873     }
1874
1875     /**
1876      * Dials a number.
1877      *
1878      * @param dialString The number to dial.
1879      * @param uusInfo The UUSInfo.
1880      * @param videoState The video state for the call.
1881      * @return The Connection.
1882      * @throws CallStateException
1883      */
1884     protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState)
1885             throws CallStateException {
1886         // dialInternal shall be overriden by GSMPhone and CDMAPhone
1887         return null;
1888     }
1889
1890     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1891         pw.println("PhoneBase:");
1892         pw.println(" mCi=" + mCi);
1893         pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
1894         pw.println(" mDcTracker=" + mDcTracker);
1895         pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
1896         pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
1897         pw.println(" mCallRingDelay=" + mCallRingDelay);
1898         pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone);
1899         pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
1900         pw.println(" mIccRecords=" + mIccRecords.get());
1901         pw.println(" mUiccApplication=" + mUiccApplication.get());
1902         pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
1903         pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
1904         pw.flush();
1905         pw.println(" mLooper=" + mLooper);
1906         pw.println(" mContext=" + mContext);
1907         pw.println(" mNotifier=" + mNotifier);
1908         pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
1909         pw.println(" mUnitTestMode=" + mUnitTestMode);
1910         pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
1911         pw.println(" getUnitTestMode()=" + getUnitTestMode());
1912         pw.println(" getState()=" + getState());
1913         pw.println(" getIccSerialNumber()=" + getIccSerialNumber());
1914         pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
1915         pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
1916         pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
1917         pw.println(" isInEmergencyCall()=" + isInEmergencyCall());
1918         pw.flush();
1919         pw.println(" isInEcm()=" + isInEcm());
1920         pw.println(" getPhoneName()=" + getPhoneName());
1921         pw.println(" getPhoneType()=" + getPhoneType());
1922         pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
1923         pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
1924         pw.println(" isDataConnectivityPossible()=" + isDataConnectivityPossible());
1925         pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
1926     }
1927
1928     /**
1929      * Returns the subscription id.
1930      */
1931     public long getSubId() {
1932         return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhoneId);
1933     }
1934
1935     /**
1936      * Returns the phone id.
1937      */
1938     public int getPhoneId() {
1939         return mPhoneId;
1940     }
1941
1942     //Gets Subscription information in the Phone Object
1943     public Subscription getSubscriptionInfo() {
1944         return mSubscriptionData;
1945     }
1946
1947     /**
1948      * Return the service state of mImsPhone if it is STATE_IN_SERVICE
1949      * otherwise return the current voice service state
1950      */
1951     @Override
1952     public int getVoicePhoneServiceState() {
1953         ImsPhone imsPhone = mImsPhone;
1954         if (imsPhone != null
1955                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
1956             return ServiceState.STATE_IN_SERVICE;
1957         }
1958         return getServiceState().getState();
1959     }
1960
1961     @Override
1962     public boolean setOperatorBrandOverride(String brand) {
1963         return false;
1964     }
1965
1966     @Override
1967     public boolean isRadioAvailable() {
1968         return mCi.getRadioState().isAvailable();
1969     }
1970
1971     @Override
1972     public void shutdownRadio() {
1973         getServiceStateTracker().requestShutdown();
1974     }
1975 }