PhoneBase.java revision 4bf323c3a37e910dd6b3eb1ffabe508e0dff5b2a
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
17package com.android.internal.telephony;
18
19import android.app.ActivityManagerNative;
20import android.app.IActivityManager;
21import android.content.Context;
22import android.content.res.Configuration;
23import android.content.SharedPreferences;
24import android.net.LinkCapabilities;
25import android.net.LinkProperties;
26import android.net.wifi.WifiManager;
27import android.os.AsyncResult;
28import android.os.Handler;
29import android.os.Looper;
30import android.os.Message;
31import android.os.RegistrantList;
32import android.os.SystemProperties;
33import android.preference.PreferenceManager;
34import android.provider.Settings;
35import android.telephony.CellInfo;
36import android.telephony.ServiceState;
37import android.telephony.SignalStrength;
38import android.text.TextUtils;
39import android.telephony.Rlog;
40
41import com.android.internal.R;
42import com.android.internal.telephony.test.SimulatedRadioControl;
43import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
44import com.android.internal.telephony.uicc.IccFileHandler;
45import com.android.internal.telephony.uicc.IccRecords;
46import com.android.internal.telephony.uicc.IsimRecords;
47import com.android.internal.telephony.uicc.SIMRecords;
48import com.android.internal.telephony.uicc.UiccCardApplication;
49import com.android.internal.telephony.uicc.UiccController;
50import com.android.internal.telephony.uicc.UsimServiceTable;
51import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
52
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
55import java.util.List;
56import java.util.Locale;
57import java.util.concurrent.atomic.AtomicReference;
58
59
60/**
61 * (<em>Not for SDK use</em>)
62 * A base implementation for the com.android.internal.telephony.Phone interface.
63 *
64 * Note that implementations of Phone.java are expected to be used
65 * from a single application thread. This should be the same thread that
66 * originally called PhoneFactory to obtain the interface.
67 *
68 *  {@hide}
69 *
70 */
71
72public abstract class PhoneBase extends Handler implements Phone {
73    private static final String LOG_TAG = "PHONE";
74    private static final boolean LOCAL_DEBUG = true;
75
76    // Key used to read and write the saved network selection numeric value
77    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
78    // Key used to read and write the saved network selection operator name
79    public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
80
81
82    // Key used to read/write "disable data connection on boot" pref (used for testing)
83    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
84
85    /* Event Constants */
86    protected static final int EVENT_RADIO_AVAILABLE             = 1;
87    /** Supplementary Service Notification received. */
88    protected static final int EVENT_SSN                         = 2;
89    protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
90    protected static final int EVENT_MMI_DONE                    = 4;
91    protected static final int EVENT_RADIO_ON                    = 5;
92    protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
93    protected static final int EVENT_USSD                        = 7;
94    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
95    protected static final int EVENT_GET_IMEI_DONE               = 9;
96    protected static final int EVENT_GET_IMEISV_DONE             = 10;
97    protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
98    protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
99    protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
100    protected static final int EVENT_CALL_RING                   = 14;
101    protected static final int EVENT_CALL_RING_CONTINUE          = 15;
102
103    // Used to intercept the carrier selection calls so that
104    // we can save the values.
105    protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
106    protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
107    protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
108    protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
109    protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
110    // Events for CDMA support
111    protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
112    protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
113    protected static final int EVENT_NV_READY                       = 23;
114    protected static final int EVENT_SET_ENHANCED_VP                = 24;
115    protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
116    protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
117    protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
118    // other
119    protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
120    protected static final int EVENT_NEW_ICC_SMS                    = 29;
121    protected static final int EVENT_ICC_RECORD_EVENTS              = 30;
122    protected static final int EVENT_ICC_CHANGED                    = 31;
123
124    // Key used to read/write current CLIR setting
125    public static final String CLIR_KEY = "clir_key";
126
127    // Key used to read/write "disable DNS server check" pref (used for testing)
128    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
129
130    /* Instance Variables */
131    public CommandsInterface mCM;
132    boolean mDnsCheckDisabled;
133    public DataConnectionTracker mDataConnectionTracker;
134    boolean mDoesRilSendMultipleCallRing;
135    int mCallRingContinueToken;
136    int mCallRingDelay;
137    public boolean mIsTheCurrentActivePhone = true;
138    boolean mIsVoiceCapable = true;
139    protected UiccController mUiccController = null;
140    public AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
141    public SmsStorageMonitor mSmsStorageMonitor;
142    public SmsUsageMonitor mSmsUsageMonitor;
143    protected AtomicReference<UiccCardApplication> mUiccApplication =
144            new AtomicReference<UiccCardApplication>();
145    public SMSDispatcher mSMS;
146
147    /**
148     * Set a system property, unless we're in unit test mode
149     */
150    public void
151    setSystemProperty(String property, String value) {
152        if(getUnitTestMode()) {
153            return;
154        }
155        SystemProperties.set(property, value);
156    }
157
158
159    protected final RegistrantList mPreciseCallStateRegistrants
160            = new RegistrantList();
161
162    protected final RegistrantList mNewRingingConnectionRegistrants
163            = new RegistrantList();
164
165    protected final RegistrantList mIncomingRingRegistrants
166            = new RegistrantList();
167
168    protected final RegistrantList mDisconnectRegistrants
169            = new RegistrantList();
170
171    protected final RegistrantList mServiceStateRegistrants
172            = new RegistrantList();
173
174    protected final RegistrantList mMmiCompleteRegistrants
175            = new RegistrantList();
176
177    protected final RegistrantList mMmiRegistrants
178            = new RegistrantList();
179
180    protected final RegistrantList mUnknownConnectionRegistrants
181            = new RegistrantList();
182
183    protected final RegistrantList mSuppServiceFailedRegistrants
184            = new RegistrantList();
185
186    protected Looper mLooper; /* to insure registrants are in correct thread*/
187
188    protected final Context mContext;
189
190    /**
191     * PhoneNotifier is an abstraction for all system-wide
192     * state change notification. DefaultPhoneNotifier is
193     * used here unless running we're inside a unit test.
194     */
195    protected PhoneNotifier mNotifier;
196
197    protected SimulatedRadioControl mSimulatedRadioControl;
198
199    boolean mUnitTestMode;
200
201    /**
202     * Constructs a PhoneBase in normal (non-unit test) mode.
203     *
204     * @param notifier An instance of DefaultPhoneNotifier,
205     * @param context Context object from hosting application
206     * unless unit testing.
207     * @param ci the CommandsInterface
208     */
209    protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
210        this(notifier, context, ci, false);
211    }
212
213    /**
214     * Constructs a PhoneBase in normal (non-unit test) mode.
215     *
216     * @param notifier An instance of DefaultPhoneNotifier,
217     * @param context Context object from hosting application
218     * unless unit testing.
219     * @param ci is CommandsInterface
220     * @param unitTestMode when true, prevents notifications
221     * of state change events
222     */
223    protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
224            boolean unitTestMode) {
225        this.mNotifier = notifier;
226        this.mContext = context;
227        mLooper = Looper.myLooper();
228        mCM = ci;
229
230        setPropertiesByCarrier();
231
232        setUnitTestMode(unitTestMode);
233
234        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
235        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
236        mCM.setOnCallRing(this, EVENT_CALL_RING, null);
237
238        /* "Voice capable" means that this device supports circuit-switched
239        * (i.e. voice) phone calls over the telephony network, and is allowed
240        * to display the in-call UI while a cellular voice call is active.
241        * This will be false on "data only" devices which can't make voice
242        * calls and don't support any in-call UI.
243        */
244        mIsVoiceCapable = mContext.getResources().getBoolean(
245                com.android.internal.R.bool.config_voice_capable);
246
247        /**
248         *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
249         *  to be generated locally. Ideally all ring tones should be loops
250         * and this wouldn't be necessary. But to minimize changes to upper
251         * layers it is requested that it be generated by lower layers.
252         *
253         * By default old phones won't have the property set but do generate
254         * the RIL_UNSOL_CALL_RING so the default if there is no property is
255         * true.
256         */
257        mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
258                TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
259        Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
260
261        mCallRingDelay = SystemProperties.getInt(
262                TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
263        Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
264
265        // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
266        mSmsStorageMonitor = new SmsStorageMonitor(this);
267        mSmsUsageMonitor = new SmsUsageMonitor(context);
268        mUiccController = UiccController.getInstance();
269        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
270    }
271
272    public void dispose() {
273        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
274            mCM.unSetOnCallRing(this);
275            // Must cleanup all connectionS and needs to use sendMessage!
276            mDataConnectionTracker.cleanUpAllConnections(null);
277            mIsTheCurrentActivePhone = false;
278            // Dispose the SMS usage and storage monitors
279            mSmsStorageMonitor.dispose();
280            mSmsUsageMonitor.dispose();
281            mUiccController.unregisterForIccChanged(this);
282        }
283    }
284
285    public void removeReferences() {
286        mSmsStorageMonitor = null;
287        mSmsUsageMonitor = null;
288        mSMS = null;
289        mIccRecords.set(null);
290        mUiccApplication.set(null);
291        mDataConnectionTracker = null;
292        mUiccController = null;
293    }
294
295    /**
296     * When overridden the derived class needs to call
297     * super.handleMessage(msg) so this method has a
298     * a chance to process the message.
299     *
300     * @param msg
301     */
302    @Override
303    public void handleMessage(Message msg) {
304        AsyncResult ar;
305
306        switch(msg.what) {
307            case EVENT_CALL_RING:
308                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
309                ar = (AsyncResult)msg.obj;
310                if (ar.exception == null) {
311                    PhoneConstants.State state = getState();
312                    if ((!mDoesRilSendMultipleCallRing)
313                            && ((state == PhoneConstants.State.RINGING) ||
314                                    (state == PhoneConstants.State.IDLE))) {
315                        mCallRingContinueToken += 1;
316                        sendIncomingCallRingNotification(mCallRingContinueToken);
317                    } else {
318                        notifyIncomingRing();
319                    }
320                }
321                break;
322
323            case EVENT_CALL_RING_CONTINUE:
324                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
325                if (getState() == PhoneConstants.State.RINGING) {
326                    sendIncomingCallRingNotification(msg.arg1);
327                }
328                break;
329
330            case EVENT_ICC_CHANGED:
331                onUpdateIccAvailability();
332                break;
333
334            default:
335                throw new RuntimeException("unexpected event not handled");
336        }
337    }
338
339    // Inherited documentation suffices.
340    public Context getContext() {
341        return mContext;
342    }
343
344    // Will be called when icc changed
345    protected abstract void onUpdateIccAvailability();
346
347    /**
348     * Disables the DNS check (i.e., allows "0.0.0.0").
349     * Useful for lab testing environment.
350     * @param b true disables the check, false enables.
351     */
352    public void disableDnsCheck(boolean b) {
353        mDnsCheckDisabled = b;
354        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
355        SharedPreferences.Editor editor = sp.edit();
356        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
357        editor.apply();
358    }
359
360    /**
361     * Returns true if the DNS check is currently disabled.
362     */
363    public boolean isDnsCheckDisabled() {
364        return mDnsCheckDisabled;
365    }
366
367    // Inherited documentation suffices.
368    public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
369        checkCorrectThread(h);
370
371        mPreciseCallStateRegistrants.addUnique(h, what, obj);
372    }
373
374    // Inherited documentation suffices.
375    public void unregisterForPreciseCallStateChanged(Handler h) {
376        mPreciseCallStateRegistrants.remove(h);
377    }
378
379    /**
380     * Subclasses of Phone probably want to replace this with a
381     * version scoped to their packages
382     */
383    protected void notifyPreciseCallStateChangedP() {
384        AsyncResult ar = new AsyncResult(null, this, null);
385        mPreciseCallStateRegistrants.notifyRegistrants(ar);
386    }
387
388    // Inherited documentation suffices.
389    public void registerForUnknownConnection(Handler h, int what, Object obj) {
390        checkCorrectThread(h);
391
392        mUnknownConnectionRegistrants.addUnique(h, what, obj);
393    }
394
395    // Inherited documentation suffices.
396    public void unregisterForUnknownConnection(Handler h) {
397        mUnknownConnectionRegistrants.remove(h);
398    }
399
400    // Inherited documentation suffices.
401    public void registerForNewRingingConnection(
402            Handler h, int what, Object obj) {
403        checkCorrectThread(h);
404
405        mNewRingingConnectionRegistrants.addUnique(h, what, obj);
406    }
407
408    // Inherited documentation suffices.
409    public void unregisterForNewRingingConnection(Handler h) {
410        mNewRingingConnectionRegistrants.remove(h);
411    }
412
413    // Inherited documentation suffices.
414    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
415        mCM.registerForInCallVoicePrivacyOn(h,what,obj);
416    }
417
418    // Inherited documentation suffices.
419    public void unregisterForInCallVoicePrivacyOn(Handler h){
420        mCM.unregisterForInCallVoicePrivacyOn(h);
421    }
422
423    // Inherited documentation suffices.
424    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
425        mCM.registerForInCallVoicePrivacyOff(h,what,obj);
426    }
427
428    // Inherited documentation suffices.
429    public void unregisterForInCallVoicePrivacyOff(Handler h){
430        mCM.unregisterForInCallVoicePrivacyOff(h);
431    }
432
433    // Inherited documentation suffices.
434    public void registerForIncomingRing(
435            Handler h, int what, Object obj) {
436        checkCorrectThread(h);
437
438        mIncomingRingRegistrants.addUnique(h, what, obj);
439    }
440
441    // Inherited documentation suffices.
442    public void unregisterForIncomingRing(Handler h) {
443        mIncomingRingRegistrants.remove(h);
444    }
445
446    // Inherited documentation suffices.
447    public void registerForDisconnect(Handler h, int what, Object obj) {
448        checkCorrectThread(h);
449
450        mDisconnectRegistrants.addUnique(h, what, obj);
451    }
452
453    // Inherited documentation suffices.
454    public void unregisterForDisconnect(Handler h) {
455        mDisconnectRegistrants.remove(h);
456    }
457
458    // Inherited documentation suffices.
459    public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
460        checkCorrectThread(h);
461
462        mSuppServiceFailedRegistrants.addUnique(h, what, obj);
463    }
464
465    // Inherited documentation suffices.
466    public void unregisterForSuppServiceFailed(Handler h) {
467        mSuppServiceFailedRegistrants.remove(h);
468    }
469
470    // Inherited documentation suffices.
471    public void registerForMmiInitiate(Handler h, int what, Object obj) {
472        checkCorrectThread(h);
473
474        mMmiRegistrants.addUnique(h, what, obj);
475    }
476
477    // Inherited documentation suffices.
478    public void unregisterForMmiInitiate(Handler h) {
479        mMmiRegistrants.remove(h);
480    }
481
482    // Inherited documentation suffices.
483    public void registerForMmiComplete(Handler h, int what, Object obj) {
484        checkCorrectThread(h);
485
486        mMmiCompleteRegistrants.addUnique(h, what, obj);
487    }
488
489    // Inherited documentation suffices.
490    public void unregisterForMmiComplete(Handler h) {
491        checkCorrectThread(h);
492
493        mMmiCompleteRegistrants.remove(h);
494    }
495
496    /**
497     * Method to retrieve the saved operator id from the Shared Preferences
498     */
499    private String getSavedNetworkSelection() {
500        // open the shared preferences and search with our key.
501        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
502        return sp.getString(NETWORK_SELECTION_KEY, "");
503    }
504
505    /**
506     * Method to restore the previously saved operator id, or reset to
507     * automatic selection, all depending upon the value in the shared
508     * preferences.
509     */
510    public void restoreSavedNetworkSelection(Message response) {
511        // retrieve the operator id
512        String networkSelection = getSavedNetworkSelection();
513
514        // set to auto if the id is empty, otherwise select the network.
515        if (TextUtils.isEmpty(networkSelection)) {
516            mCM.setNetworkSelectionModeAutomatic(response);
517        } else {
518            mCM.setNetworkSelectionModeManual(networkSelection, response);
519        }
520    }
521
522    // Inherited documentation suffices.
523    public void setUnitTestMode(boolean f) {
524        mUnitTestMode = f;
525    }
526
527    // Inherited documentation suffices.
528    public boolean getUnitTestMode() {
529        return mUnitTestMode;
530    }
531
532    /**
533     * To be invoked when a voice call Connection disconnects.
534     *
535     * Subclasses of Phone probably want to replace this with a
536     * version scoped to their packages
537     */
538    protected void notifyDisconnectP(Connection cn) {
539        AsyncResult ar = new AsyncResult(null, cn, null);
540        mDisconnectRegistrants.notifyRegistrants(ar);
541    }
542
543    // Inherited documentation suffices.
544    public void registerForServiceStateChanged(
545            Handler h, int what, Object obj) {
546        checkCorrectThread(h);
547
548        mServiceStateRegistrants.add(h, what, obj);
549    }
550
551    // Inherited documentation suffices.
552    public void unregisterForServiceStateChanged(Handler h) {
553        mServiceStateRegistrants.remove(h);
554    }
555
556    // Inherited documentation suffices.
557    public void registerForRingbackTone(Handler h, int what, Object obj) {
558        mCM.registerForRingbackTone(h,what,obj);
559    }
560
561    // Inherited documentation suffices.
562    public void unregisterForRingbackTone(Handler h) {
563        mCM.unregisterForRingbackTone(h);
564    }
565
566    // Inherited documentation suffices.
567    public void registerForResendIncallMute(Handler h, int what, Object obj) {
568        mCM.registerForResendIncallMute(h,what,obj);
569    }
570
571    // Inherited documentation suffices.
572    public void unregisterForResendIncallMute(Handler h) {
573        mCM.unregisterForResendIncallMute(h);
574    }
575
576    public void setEchoSuppressionEnabled(boolean enabled) {
577        // no need for regular phone
578    }
579
580    /**
581     * Subclasses of Phone probably want to replace this with a
582     * version scoped to their packages
583     */
584    protected void notifyServiceStateChangedP(ServiceState ss) {
585        AsyncResult ar = new AsyncResult(null, ss, null);
586        mServiceStateRegistrants.notifyRegistrants(ar);
587
588        mNotifier.notifyServiceState(this);
589    }
590
591    // Inherited documentation suffices.
592    public SimulatedRadioControl getSimulatedRadioControl() {
593        return mSimulatedRadioControl;
594    }
595
596    /**
597     * Verifies the current thread is the same as the thread originally
598     * used in the initialization of this instance. Throws RuntimeException
599     * if not.
600     *
601     * @exception RuntimeException if the current thread is not
602     * the thread that originally obtained this PhoneBase instance.
603     */
604    private void checkCorrectThread(Handler h) {
605        if (h.getLooper() != mLooper) {
606            throw new RuntimeException(
607                    "com.android.internal.telephony.Phone must be used from within one thread");
608        }
609    }
610
611    /**
612     * Set the properties by matching the carrier string in
613     * a string-array resource
614     */
615    private void setPropertiesByCarrier() {
616        String carrier = SystemProperties.get("ro.carrier");
617
618        if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
619            return;
620        }
621
622        CharSequence[] carrierLocales = mContext.
623                getResources().getTextArray(R.array.carrier_properties);
624
625        for (int i = 0; i < carrierLocales.length; i+=3) {
626            String c = carrierLocales[i].toString();
627            if (carrier.equals(c)) {
628                String l = carrierLocales[i+1].toString();
629
630                String language = l.substring(0, 2);
631                String country = "";
632                if (l.length() >=5) {
633                    country = l.substring(3, 5);
634                }
635                MccTable.setSystemLocale(mContext, language, country);
636
637                if (!country.isEmpty()) {
638                    try {
639                        Settings.Global.getInt(mContext.getContentResolver(),
640                                Settings.Global.WIFI_COUNTRY_CODE);
641                    } catch (Settings.SettingNotFoundException e) {
642                        // note this is not persisting
643                        WifiManager wM = (WifiManager)
644                                mContext.getSystemService(Context.WIFI_SERVICE);
645                        wM.setCountryCode(country, false);
646                    }
647                }
648                return;
649            }
650        }
651    }
652
653    /**
654     * Get state
655     */
656    public abstract PhoneConstants.State getState();
657
658    /**
659     * Retrieves the IccFileHandler of the Phone instance
660     */
661    public IccFileHandler getIccFileHandler(){
662        UiccCardApplication uiccApplication = mUiccApplication.get();
663        if (uiccApplication == null) return null;
664        return uiccApplication.getIccFileHandler();
665    }
666
667    /*
668     * Retrieves the Handler of the Phone instance
669     */
670    public Handler getHandler() {
671        return this;
672    }
673
674    /**
675    * Retrieves the ServiceStateTracker of the phone instance.
676    */
677    public ServiceStateTracker getServiceStateTracker() {
678        return null;
679    }
680
681    /**
682    * Get call tracker
683    */
684    public CallTracker getCallTracker() {
685        return null;
686    }
687
688    public AppType getCurrentUiccAppType() {
689        UiccCardApplication currentApp = mUiccApplication.get();
690        if (currentApp != null) {
691            return currentApp.getType();
692        }
693        return AppType.APPTYPE_UNKNOWN;
694    }
695
696    @Override
697    public IccCard getIccCard() {
698        return null;
699        //throw new Exception("getIccCard Shouldn't be called from PhoneBase");
700    }
701
702    @Override
703    public String getIccSerialNumber() {
704        IccRecords r = mIccRecords.get();
705        return (r != null) ? r.iccid : null;
706    }
707
708    @Override
709    public boolean getIccRecordsLoaded() {
710        IccRecords r = mIccRecords.get();
711        return (r != null) ? r.getRecordsLoaded() : false;
712    }
713
714    /**
715     * @return all available cell information or null if none.
716     */
717    @Override
718    public List<CellInfo> getAllCellInfo() {
719        return getServiceStateTracker().getAllCellInfo();
720    }
721
722    @Override
723    public boolean getMessageWaitingIndicator() {
724        IccRecords r = mIccRecords.get();
725        return (r != null) ? r.getVoiceMessageWaiting() : false;
726    }
727
728    @Override
729    public boolean getCallForwardingIndicator() {
730        IccRecords r = mIccRecords.get();
731        return (r != null) ? r.getVoiceCallForwardingFlag() : false;
732    }
733
734    /**
735     *  Query the status of the CDMA roaming preference
736     */
737    public void queryCdmaRoamingPreference(Message response) {
738        mCM.queryCdmaRoamingPreference(response);
739    }
740
741    /**
742     * Get the signal strength
743     */
744    @Override
745    public SignalStrength getSignalStrength() {
746        ServiceStateTracker sst = getServiceStateTracker();
747        if (sst == null) {
748            return new SignalStrength();
749        } else {
750            return sst.getSignalStrength();
751        }
752    }
753
754    /**
755     *  Set the status of the CDMA roaming preference
756     */
757    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
758        mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
759    }
760
761    /**
762     *  Set the status of the CDMA subscription mode
763     */
764    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
765        mCM.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
766    }
767
768    /**
769     *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
770     */
771    public void setPreferredNetworkType(int networkType, Message response) {
772        mCM.setPreferredNetworkType(networkType, response);
773    }
774
775    public void getPreferredNetworkType(Message response) {
776        mCM.getPreferredNetworkType(response);
777    }
778
779    public void getSmscAddress(Message result) {
780        mCM.getSmscAddress(result);
781    }
782
783    public void setSmscAddress(String address, Message result) {
784        mCM.setSmscAddress(address, result);
785    }
786
787    public void setTTYMode(int ttyMode, Message onComplete) {
788        mCM.setTTYMode(ttyMode, onComplete);
789    }
790
791    public void queryTTYMode(Message onComplete) {
792        mCM.queryTTYMode(onComplete);
793    }
794
795    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
796        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
797        logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
798    }
799
800    public void getEnhancedVoicePrivacy(Message onComplete) {
801        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
802        logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
803    }
804
805    public void setBandMode(int bandMode, Message response) {
806        mCM.setBandMode(bandMode, response);
807    }
808
809    public void queryAvailableBandMode(Message response) {
810        mCM.queryAvailableBandMode(response);
811    }
812
813    public void invokeOemRilRequestRaw(byte[] data, Message response) {
814        mCM.invokeOemRilRequestRaw(data, response);
815    }
816
817    public void invokeOemRilRequestStrings(String[] strings, Message response) {
818        mCM.invokeOemRilRequestStrings(strings, response);
819    }
820
821    public void notifyDataActivity() {
822        mNotifier.notifyDataActivity(this);
823    }
824
825    public void notifyMessageWaitingIndicator() {
826        // Do not notify voice mail waiting if device doesn't support voice
827        if (!mIsVoiceCapable)
828            return;
829
830        // This function is added to send the notification to DefaultPhoneNotifier.
831        mNotifier.notifyMessageWaitingChanged(this);
832    }
833
834    public void notifyDataConnection(String reason, String apnType,
835            PhoneConstants.DataState state) {
836        mNotifier.notifyDataConnection(this, reason, apnType, state);
837    }
838
839    public void notifyDataConnection(String reason, String apnType) {
840        mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
841    }
842
843    public void notifyDataConnection(String reason) {
844        String types[] = getActiveApnTypes();
845        for (String apnType : types) {
846            mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
847        }
848    }
849
850    public void notifyOtaspChanged(int otaspMode) {
851        mNotifier.notifyOtaspChanged(this, otaspMode);
852    }
853
854    public void notifySignalStrength() {
855        mNotifier.notifySignalStrength(this);
856    }
857
858    public void notifyCellInfo(List<CellInfo> cellInfo) {
859        mNotifier.notifyCellInfo(this, cellInfo);
860    }
861
862    /**
863     * @return true if a mobile originating emergency call is active
864     */
865    public boolean isInEmergencyCall() {
866        return false;
867    }
868
869    /**
870     * @return true if we are in the emergency call back mode. This is a period where
871     * the phone should be using as little power as possible and be ready to receive an
872     * incoming call from the emergency operator.
873     */
874    public boolean isInEcm() {
875        return false;
876    }
877
878    public abstract String getPhoneName();
879
880    public abstract int getPhoneType();
881
882    /** @hide */
883    public int getVoiceMessageCount(){
884        return 0;
885    }
886
887    /**
888     * Returns the CDMA ERI icon index to display
889     */
890    public int getCdmaEriIconIndex() {
891        logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
892        return -1;
893    }
894
895    /**
896     * Returns the CDMA ERI icon mode,
897     * 0 - ON
898     * 1 - FLASHING
899     */
900    public int getCdmaEriIconMode() {
901        logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
902        return -1;
903    }
904
905    /**
906     * Returns the CDMA ERI text,
907     */
908    public String getCdmaEriText() {
909        logUnexpectedCdmaMethodCall("getCdmaEriText");
910        return "GSM nw, no ERI";
911    }
912
913    public String getCdmaMin() {
914        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
915        logUnexpectedCdmaMethodCall("getCdmaMin");
916        return null;
917    }
918
919    public boolean isMinInfoReady() {
920        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
921        logUnexpectedCdmaMethodCall("isMinInfoReady");
922        return false;
923    }
924
925    public String getCdmaPrlVersion(){
926        //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
927        logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
928        return null;
929    }
930
931    public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
932        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
933        logUnexpectedCdmaMethodCall("sendBurstDtmf");
934    }
935
936    public void exitEmergencyCallbackMode() {
937        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
938        logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
939    }
940
941    public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
942        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
943        logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
944    }
945
946    public void unregisterForCdmaOtaStatusChange(Handler h) {
947        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
948        logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
949    }
950
951    public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
952        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
953        logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
954    }
955
956    public void unregisterForSubscriptionInfoReady(Handler h) {
957        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
958        logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
959    }
960
961    /**
962     * Returns true if OTA Service Provisioning needs to be performed.
963     * If not overridden return false.
964     */
965    public boolean needsOtaServiceProvisioning() {
966        return false;
967    }
968
969    /**
970     * Return true if number is an OTASP number.
971     * If not overridden return false.
972     */
973    public  boolean isOtaSpNumber(String dialStr) {
974        return false;
975    }
976
977    public void registerForCallWaiting(Handler h, int what, Object obj){
978        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
979        logUnexpectedCdmaMethodCall("registerForCallWaiting");
980    }
981
982    public void unregisterForCallWaiting(Handler h){
983        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
984        logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
985    }
986
987    public void registerForEcmTimerReset(Handler h, int what, Object obj) {
988        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
989        logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
990    }
991
992    public void unregisterForEcmTimerReset(Handler h) {
993        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
994        logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
995    }
996
997    public void registerForSignalInfo(Handler h, int what, Object obj) {
998        mCM.registerForSignalInfo(h, what, obj);
999    }
1000
1001    public void unregisterForSignalInfo(Handler h) {
1002        mCM.unregisterForSignalInfo(h);
1003    }
1004
1005    public void registerForDisplayInfo(Handler h, int what, Object obj) {
1006        mCM.registerForDisplayInfo(h, what, obj);
1007    }
1008
1009     public void unregisterForDisplayInfo(Handler h) {
1010         mCM.unregisterForDisplayInfo(h);
1011     }
1012
1013    public void registerForNumberInfo(Handler h, int what, Object obj) {
1014        mCM.registerForNumberInfo(h, what, obj);
1015    }
1016
1017    public void unregisterForNumberInfo(Handler h) {
1018        mCM.unregisterForNumberInfo(h);
1019    }
1020
1021    public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
1022        mCM.registerForRedirectedNumberInfo(h, what, obj);
1023    }
1024
1025    public void unregisterForRedirectedNumberInfo(Handler h) {
1026        mCM.unregisterForRedirectedNumberInfo(h);
1027    }
1028
1029    public void registerForLineControlInfo(Handler h, int what, Object obj) {
1030        mCM.registerForLineControlInfo( h, what, obj);
1031    }
1032
1033    public void unregisterForLineControlInfo(Handler h) {
1034        mCM.unregisterForLineControlInfo(h);
1035    }
1036
1037    public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
1038        mCM.registerFoT53ClirlInfo(h, what, obj);
1039    }
1040
1041    public void unregisterForT53ClirInfo(Handler h) {
1042        mCM.unregisterForT53ClirInfo(h);
1043    }
1044
1045    public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
1046        mCM.registerForT53AudioControlInfo( h, what, obj);
1047    }
1048
1049    public void unregisterForT53AudioControlInfo(Handler h) {
1050        mCM.unregisterForT53AudioControlInfo(h);
1051    }
1052
1053     public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
1054         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1055         logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
1056     }
1057
1058     public void unsetOnEcbModeExitResponse(Handler h){
1059        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1060         logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
1061     }
1062
1063    public String[] getActiveApnTypes() {
1064        return mDataConnectionTracker.getActiveApnTypes();
1065    }
1066
1067    public String getActiveApnHost(String apnType) {
1068        return mDataConnectionTracker.getActiveApnString(apnType);
1069    }
1070
1071    public LinkProperties getLinkProperties(String apnType) {
1072        return mDataConnectionTracker.getLinkProperties(apnType);
1073    }
1074
1075    public LinkCapabilities getLinkCapabilities(String apnType) {
1076        return mDataConnectionTracker.getLinkCapabilities(apnType);
1077    }
1078
1079    public int enableApnType(String type) {
1080        return mDataConnectionTracker.enableApnType(type);
1081    }
1082
1083    public int disableApnType(String type) {
1084        return mDataConnectionTracker.disableApnType(type);
1085    }
1086
1087    public boolean isDataConnectivityPossible() {
1088        return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
1089    }
1090
1091    public boolean isDataConnectivityPossible(String apnType) {
1092        return ((mDataConnectionTracker != null) &&
1093                (mDataConnectionTracker.isDataPossible(apnType)));
1094    }
1095
1096    /**
1097     * Notify registrants of a new ringing Connection.
1098     * Subclasses of Phone probably want to replace this with a
1099     * version scoped to their packages
1100     */
1101    protected void notifyNewRingingConnectionP(Connection cn) {
1102        if (!mIsVoiceCapable)
1103            return;
1104        AsyncResult ar = new AsyncResult(null, cn, null);
1105        mNewRingingConnectionRegistrants.notifyRegistrants(ar);
1106    }
1107
1108    /**
1109     * Notify registrants of a RING event.
1110     */
1111    private void notifyIncomingRing() {
1112        if (!mIsVoiceCapable)
1113            return;
1114        AsyncResult ar = new AsyncResult(null, this, null);
1115        mIncomingRingRegistrants.notifyRegistrants(ar);
1116    }
1117
1118    /**
1119     * Send the incoming call Ring notification if conditions are right.
1120     */
1121    private void sendIncomingCallRingNotification(int token) {
1122        if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
1123                (token == mCallRingContinueToken)) {
1124            Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
1125            notifyIncomingRing();
1126            sendMessageDelayed(
1127                    obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
1128        } else {
1129            Rlog.d(LOG_TAG, "Ignoring ring notification request,"
1130                    + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
1131                    + " token=" + token
1132                    + " mCallRingContinueToken=" + mCallRingContinueToken
1133                    + " mIsVoiceCapable=" + mIsVoiceCapable);
1134        }
1135    }
1136
1137    public boolean isCspPlmnEnabled() {
1138        // This function should be overridden by the class GSMPhone.
1139        // Not implemented in CDMAPhone.
1140        logUnexpectedGsmMethodCall("isCspPlmnEnabled");
1141        return false;
1142    }
1143
1144    public IsimRecords getIsimRecords() {
1145        Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
1146        return null;
1147    }
1148
1149    public void requestIsimAuthentication(String nonce, Message result) {
1150        Rlog.e(LOG_TAG, "requestIsimAuthentication() is only supported on LTE devices");
1151    }
1152
1153    public String getMsisdn() {
1154        logUnexpectedGsmMethodCall("getMsisdn");
1155        return null;
1156    }
1157
1158    /**
1159     * Common error logger method for unexpected calls to CDMA-only methods.
1160     */
1161    private static void logUnexpectedCdmaMethodCall(String name)
1162    {
1163        Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1164                "called, CDMAPhone inactive.");
1165    }
1166
1167    public PhoneConstants.DataState getDataConnectionState() {
1168        return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
1169    }
1170
1171    /**
1172     * Common error logger method for unexpected calls to GSM/WCDMA-only methods.
1173     */
1174    private static void logUnexpectedGsmMethodCall(String name) {
1175        Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1176                "called, GSMPhone inactive.");
1177    }
1178
1179    // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
1180    public void notifyCallForwardingIndicator() {
1181        // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
1182        Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
1183    }
1184
1185    public void notifyDataConnectionFailed(String reason, String apnType) {
1186        mNotifier.notifyDataConnectionFailed(this, reason, apnType);
1187    }
1188
1189    /**
1190     * {@inheritDoc}
1191     */
1192    @Override
1193    public int getLteOnCdmaMode() {
1194        return mCM.getLteOnCdmaMode();
1195    }
1196
1197    /**
1198     * Sets the SIM voice message waiting indicator records.
1199     * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
1200     * @param countWaiting The number of messages waiting, if known. Use
1201     *                     -1 to indicate that an unknown number of
1202     *                      messages are waiting
1203     */
1204    @Override
1205    public void setVoiceMessageWaiting(int line, int countWaiting) {
1206        IccRecords r = mIccRecords.get();
1207        if (r != null) {
1208            r.setVoiceMessageWaiting(line, countWaiting);
1209        }
1210    }
1211
1212    /**
1213     * Gets the USIM service table from the UICC, if present and available.
1214     * @return an interface to the UsimServiceTable record, or null if not available
1215     */
1216    @Override
1217    public UsimServiceTable getUsimServiceTable() {
1218        IccRecords r = mIccRecords.get();
1219        return (r != null) ? r.getUsimServiceTable() : null;
1220    }
1221
1222    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1223        pw.println("PhoneBase:");
1224        pw.println(" mCM=" + mCM);
1225        pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
1226        pw.println(" mDataConnectionTracker=" + mDataConnectionTracker);
1227        pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
1228        pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
1229        pw.println(" mCallRingDelay=" + mCallRingDelay);
1230        pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone);
1231        pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
1232        pw.println(" mIccRecords=" + mIccRecords.get());
1233        pw.println(" mUiccApplication=" + mUiccApplication.get());
1234        pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
1235        pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
1236        pw.println(" mSMS=" + mSMS);
1237        pw.flush();
1238        pw.println(" mLooper=" + mLooper);
1239        pw.println(" mContext=" + mContext);
1240        pw.println(" mNotifier=" + mNotifier);
1241        pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
1242        pw.println(" mUnitTestMode=" + mUnitTestMode);
1243        pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
1244        pw.println(" getUnitTestMode()=" + getUnitTestMode());
1245        pw.println(" getState()=" + getState());
1246        pw.println(" getIccSerialNumber()=" + getIccSerialNumber());
1247        pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
1248        pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
1249        pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
1250        pw.println(" isInEmergencyCall()=" + isInEmergencyCall());
1251        pw.flush();
1252        pw.println(" isInEcm()=" + isInEcm());
1253        pw.println(" getPhoneName()=" + getPhoneName());
1254        pw.println(" getPhoneType()=" + getPhoneType());
1255        pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
1256        pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
1257        pw.println(" isDataConnectivityPossible()=" + isDataConnectivityPossible());
1258        pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
1259    }
1260}
1261