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