This routine returns integer values defined in the Phone interface, derived from RILConstants values. Direct references to the RILConstants are replaced by references to these new ones for consistency. API CHANGE: unhide TelephonyManager.PHONE_TYPE_CDMA Addresses issue: http://buganizer/issue?id=1905415 Change-Id: Icfec6d457231b098c031677a66770b5e57be4a44
1018 lines
35 KiB
Java
1018 lines
35 KiB
Java
/*
|
|
* Copyright (C) 2007 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.internal.telephony;
|
|
|
|
import android.app.ActivityManagerNative;
|
|
import android.app.IActivityManager;
|
|
import android.content.Context;
|
|
import android.content.res.Configuration;
|
|
import android.content.SharedPreferences;
|
|
import android.net.wifi.WifiManager;
|
|
import android.os.AsyncResult;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.os.Message;
|
|
import android.os.RegistrantList;
|
|
import android.os.SystemProperties;
|
|
import android.preference.PreferenceManager;
|
|
import android.provider.Settings;
|
|
import android.telephony.ServiceState;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import com.android.internal.R;
|
|
import com.android.internal.telephony.gsm.PdpConnection;
|
|
import com.android.internal.telephony.test.SimulatedRadioControl;
|
|
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
|
|
/**
|
|
* (<em>Not for SDK use</em>)
|
|
* A base implementation for the com.android.internal.telephony.Phone interface.
|
|
*
|
|
* Note that implementations of Phone.java are expected to be used
|
|
* from a single application thread. This should be the same thread that
|
|
* originally called PhoneFactory to obtain the interface.
|
|
*
|
|
* {@hide}
|
|
*
|
|
*/
|
|
|
|
public abstract class PhoneBase extends Handler implements Phone {
|
|
private static final String LOG_TAG = "PHONE";
|
|
private static final boolean LOCAL_DEBUG = true;
|
|
|
|
// Key used to read and write the saved network selection numeric value
|
|
public static final String NETWORK_SELECTION_KEY = "network_selection_key";
|
|
// Key used to read and write the saved network selection operator name
|
|
public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
|
|
|
|
|
|
// Key used to read/write "disable data connection on boot" pref (used for testing)
|
|
public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
|
|
|
|
/* Event Constants */
|
|
protected static final int EVENT_RADIO_AVAILABLE = 1;
|
|
/** Supplementary Service Notification received. */
|
|
protected static final int EVENT_SSN = 2;
|
|
protected static final int EVENT_SIM_RECORDS_LOADED = 3;
|
|
protected static final int EVENT_MMI_DONE = 4;
|
|
protected static final int EVENT_RADIO_ON = 5;
|
|
protected static final int EVENT_GET_BASEBAND_VERSION_DONE = 6;
|
|
protected static final int EVENT_USSD = 7;
|
|
protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 8;
|
|
protected static final int EVENT_GET_IMEI_DONE = 9;
|
|
protected static final int EVENT_GET_IMEISV_DONE = 10;
|
|
protected static final int EVENT_GET_SIM_STATUS_DONE = 11;
|
|
protected static final int EVENT_SET_CALL_FORWARD_DONE = 12;
|
|
protected static final int EVENT_GET_CALL_FORWARD_DONE = 13;
|
|
protected static final int EVENT_CALL_RING = 14;
|
|
protected static final int EVENT_CALL_RING_CONTINUE = 15;
|
|
|
|
// Used to intercept the carrier selection calls so that
|
|
// we can save the values.
|
|
protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 16;
|
|
protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
|
|
protected static final int EVENT_SET_CLIR_COMPLETE = 18;
|
|
protected static final int EVENT_REGISTERED_TO_NETWORK = 19;
|
|
protected static final int EVENT_SET_VM_NUMBER_DONE = 20;
|
|
// Events for CDMA support
|
|
protected static final int EVENT_GET_DEVICE_IDENTITY_DONE = 21;
|
|
protected static final int EVENT_RUIM_RECORDS_LOADED = 22;
|
|
protected static final int EVENT_NV_READY = 23;
|
|
protected static final int EVENT_SET_ENHANCED_VP = 24;
|
|
protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER = 25;
|
|
protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
|
|
|
|
// Key used to read/write current CLIR setting
|
|
public static final String CLIR_KEY = "clir_key";
|
|
|
|
// Key used to read/write "disable DNS server check" pref (used for testing)
|
|
public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
|
|
|
|
/* Instance Variables */
|
|
public CommandsInterface mCM;
|
|
protected IccFileHandler mIccFileHandler;
|
|
boolean mDnsCheckDisabled = false;
|
|
public DataConnectionTracker mDataConnection;
|
|
boolean mDoesRilSendMultipleCallRing;
|
|
int mCallRingContinueToken = 0;
|
|
int mCallRingDelay;
|
|
|
|
/**
|
|
* Set a system property, unless we're in unit test mode
|
|
*/
|
|
public void
|
|
setSystemProperty(String property, String value) {
|
|
if(getUnitTestMode()) {
|
|
return;
|
|
}
|
|
SystemProperties.set(property, value);
|
|
}
|
|
|
|
|
|
protected final RegistrantList mPreciseCallStateRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mNewRingingConnectionRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mIncomingRingRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mDisconnectRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mServiceStateRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mMmiCompleteRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mMmiRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mUnknownConnectionRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected final RegistrantList mSuppServiceFailedRegistrants
|
|
= new RegistrantList();
|
|
|
|
protected Looper mLooper; /* to insure registrants are in correct thread*/
|
|
|
|
protected Context mContext;
|
|
|
|
/**
|
|
* PhoneNotifier is an abstraction for all system-wide
|
|
* state change notification. DefaultPhoneNotifier is
|
|
* used here unless running we're inside a unit test.
|
|
*/
|
|
protected PhoneNotifier mNotifier;
|
|
|
|
protected SimulatedRadioControl mSimulatedRadioControl;
|
|
|
|
boolean mUnitTestMode;
|
|
|
|
/**
|
|
* Constructs a PhoneBase in normal (non-unit test) mode.
|
|
*
|
|
* @param context Context object from hosting application
|
|
* @param notifier An instance of DefaultPhoneNotifier,
|
|
* unless unit testing.
|
|
*/
|
|
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
|
|
this(notifier, context, ci, false);
|
|
}
|
|
|
|
/**
|
|
* Constructs a PhoneBase in normal (non-unit test) mode.
|
|
*
|
|
* @param context Context object from hosting application
|
|
* @param notifier An instance of DefaultPhoneNotifier,
|
|
* unless unit testing.
|
|
* @param unitTestMode when true, prevents notifications
|
|
* of state change events
|
|
*/
|
|
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
|
|
boolean unitTestMode) {
|
|
this.mNotifier = notifier;
|
|
this.mContext = context;
|
|
mLooper = Looper.myLooper();
|
|
mCM = ci;
|
|
|
|
setPropertiesByCarrier();
|
|
|
|
setUnitTestMode(unitTestMode);
|
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
|
mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
|
|
mCM.setOnCallRing(this, EVENT_CALL_RING, null);
|
|
|
|
/**
|
|
* Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
|
|
* to be generated locally. Ideally all ring tones should be loops
|
|
* and this wouldn't be necessary. But to minimize changes to upper
|
|
* layers it is requested that it be generated by lower layers.
|
|
*
|
|
* By default old phones won't have the property set but do generate
|
|
* the RIL_UNSOL_CALL_RING so the default if there is no property is
|
|
* true.
|
|
*/
|
|
mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
|
|
TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
|
|
Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
|
|
|
|
mCallRingDelay = SystemProperties.getInt(
|
|
TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
|
|
Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
|
|
}
|
|
|
|
public void dispose() {
|
|
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
|
|
mCM.unSetOnCallRing(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* When overridden the derived class needs to call
|
|
* super.handleMessage(msg) so this method has a
|
|
* a chance to process the message.
|
|
*
|
|
* @param msg
|
|
*/
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
AsyncResult ar;
|
|
|
|
switch(msg.what) {
|
|
case EVENT_CALL_RING:
|
|
Log.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
|
|
ar = (AsyncResult)msg.obj;
|
|
if (ar.exception == null) {
|
|
Phone.State state = getState();
|
|
if ((!mDoesRilSendMultipleCallRing)
|
|
&& ((state == Phone.State.RINGING) || (state == Phone.State.IDLE))) {
|
|
mCallRingContinueToken += 1;
|
|
sendIncomingCallRingNotification(mCallRingContinueToken);
|
|
} else {
|
|
notifyIncomingRing();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EVENT_CALL_RING_CONTINUE:
|
|
Log.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
|
|
if (getState() == Phone.State.RINGING) {
|
|
sendIncomingCallRingNotification(msg.arg1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw new RuntimeException("unexpected event not handled");
|
|
}
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public Context getContext() {
|
|
return mContext;
|
|
}
|
|
|
|
/**
|
|
* Disables the DNS check (i.e., allows "0.0.0.0").
|
|
* Useful for lab testing environment.
|
|
* @param b true disables the check, false enables.
|
|
*/
|
|
public void disableDnsCheck(boolean b) {
|
|
mDnsCheckDisabled = b;
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
|
SharedPreferences.Editor editor = sp.edit();
|
|
editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
|
|
editor.commit();
|
|
}
|
|
|
|
/**
|
|
* Returns true if the DNS check is currently disabled.
|
|
*/
|
|
public boolean isDnsCheckDisabled() {
|
|
return mDnsCheckDisabled;
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mPreciseCallStateRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForPreciseCallStateChanged(Handler h) {
|
|
mPreciseCallStateRegistrants.remove(h);
|
|
}
|
|
|
|
/**
|
|
* Subclasses of Phone probably want to replace this with a
|
|
* version scoped to their packages
|
|
*/
|
|
protected void notifyPreciseCallStateChangedP() {
|
|
AsyncResult ar = new AsyncResult(null, this, null);
|
|
mPreciseCallStateRegistrants.notifyRegistrants(ar);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForUnknownConnection(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mUnknownConnectionRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForUnknownConnection(Handler h) {
|
|
mUnknownConnectionRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForNewRingingConnection(
|
|
Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mNewRingingConnectionRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForNewRingingConnection(Handler h) {
|
|
mNewRingingConnectionRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
|
|
mCM.registerForInCallVoicePrivacyOn(h,what,obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForInCallVoicePrivacyOn(Handler h){
|
|
mCM.unregisterForInCallVoicePrivacyOn(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
|
|
mCM.registerForInCallVoicePrivacyOff(h,what,obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForInCallVoicePrivacyOff(Handler h){
|
|
mCM.unregisterForInCallVoicePrivacyOff(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForIncomingRing(
|
|
Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mIncomingRingRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForIncomingRing(Handler h) {
|
|
mIncomingRingRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForDisconnect(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mDisconnectRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForDisconnect(Handler h) {
|
|
mDisconnectRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mSuppServiceFailedRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForSuppServiceFailed(Handler h) {
|
|
mSuppServiceFailedRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForMmiInitiate(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mMmiRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForMmiInitiate(Handler h) {
|
|
mMmiRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForMmiComplete(Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mMmiCompleteRegistrants.addUnique(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForMmiComplete(Handler h) {
|
|
checkCorrectThread(h);
|
|
|
|
mMmiCompleteRegistrants.remove(h);
|
|
}
|
|
|
|
/**
|
|
* Method to retrieve the saved operator id from the Shared Preferences
|
|
*/
|
|
private String getSavedNetworkSelection() {
|
|
// open the shared preferences and search with our key.
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
|
return sp.getString(NETWORK_SELECTION_KEY, "");
|
|
}
|
|
|
|
/**
|
|
* Method to restore the previously saved operator id, or reset to
|
|
* automatic selection, all depending upon the value in the shared
|
|
* preferences.
|
|
*/
|
|
public void restoreSavedNetworkSelection(Message response) {
|
|
// retrieve the operator id
|
|
String networkSelection = getSavedNetworkSelection();
|
|
|
|
// set to auto if the id is empty, otherwise select the network.
|
|
if (TextUtils.isEmpty(networkSelection)) {
|
|
mCM.setNetworkSelectionModeAutomatic(response);
|
|
} else {
|
|
mCM.setNetworkSelectionModeManual(networkSelection, response);
|
|
}
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void setUnitTestMode(boolean f) {
|
|
mUnitTestMode = f;
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public boolean getUnitTestMode() {
|
|
return mUnitTestMode;
|
|
}
|
|
|
|
/**
|
|
* To be invoked when a voice call Connection disconnects.
|
|
*
|
|
* Subclasses of Phone probably want to replace this with a
|
|
* version scoped to their packages
|
|
*/
|
|
protected void notifyDisconnectP(Connection cn) {
|
|
AsyncResult ar = new AsyncResult(null, cn, null);
|
|
mDisconnectRegistrants.notifyRegistrants(ar);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForServiceStateChanged(
|
|
Handler h, int what, Object obj) {
|
|
checkCorrectThread(h);
|
|
|
|
mServiceStateRegistrants.add(h, what, obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForServiceStateChanged(Handler h) {
|
|
mServiceStateRegistrants.remove(h);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void registerForRingbackTone(Handler h, int what, Object obj) {
|
|
mCM.registerForRingbackTone(h,what,obj);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public void unregisterForRingbackTone(Handler h) {
|
|
mCM.unregisterForRingbackTone(h);
|
|
}
|
|
|
|
/**
|
|
* Subclasses of Phone probably want to replace this with a
|
|
* version scoped to their packages
|
|
*/
|
|
protected void notifyServiceStateChangedP(ServiceState ss) {
|
|
AsyncResult ar = new AsyncResult(null, ss, null);
|
|
mServiceStateRegistrants.notifyRegistrants(ar);
|
|
|
|
mNotifier.notifyServiceState(this);
|
|
}
|
|
|
|
// Inherited documentation suffices.
|
|
public SimulatedRadioControl getSimulatedRadioControl() {
|
|
return mSimulatedRadioControl;
|
|
}
|
|
|
|
/**
|
|
* Verifies the current thread is the same as the thread originally
|
|
* used in the initialization of this instance. Throws RuntimeException
|
|
* if not.
|
|
*
|
|
* @exception RuntimeException if the current thread is not
|
|
* the thread that originally obtained this PhoneBase instance.
|
|
*/
|
|
private void checkCorrectThread(Handler h) {
|
|
if (h.getLooper() != mLooper) {
|
|
throw new RuntimeException(
|
|
"com.android.internal.telephony.Phone must be used from within one thread");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the properties by matching the carrier string in
|
|
* a string-array resource
|
|
*/
|
|
private void setPropertiesByCarrier() {
|
|
String carrier = SystemProperties.get("ro.carrier");
|
|
|
|
if (null == carrier || 0 == carrier.length()) {
|
|
return;
|
|
}
|
|
|
|
CharSequence[] carrierLocales = mContext.
|
|
getResources().getTextArray(R.array.carrier_properties);
|
|
|
|
for (int i = 0; i < carrierLocales.length; i+=3) {
|
|
String c = carrierLocales[i].toString();
|
|
if (carrier.equals(c)) {
|
|
String l = carrierLocales[i+1].toString();
|
|
int wifiChannels = 0;
|
|
try {
|
|
wifiChannels = Integer.parseInt(
|
|
carrierLocales[i+2].toString());
|
|
} catch (NumberFormatException e) { }
|
|
|
|
String language = l.substring(0, 2);
|
|
String country = "";
|
|
if (l.length() >=5) {
|
|
country = l.substring(3, 5);
|
|
}
|
|
setSystemLocale(language, country);
|
|
|
|
if (wifiChannels != 0) {
|
|
try {
|
|
Settings.Secure.getInt(mContext.getContentResolver(),
|
|
Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
|
|
} catch (Settings.SettingNotFoundException e) {
|
|
// note this is not persisting
|
|
WifiManager wM = (WifiManager)
|
|
mContext.getSystemService(Context.WIFI_SERVICE);
|
|
wM.setNumAllowedChannels(wifiChannels, false);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility code to set the system locale if it's not set already
|
|
* @param langauge Two character language code desired
|
|
* @param country Two character country code desired
|
|
*
|
|
* {@hide}
|
|
*/
|
|
public void setSystemLocale(String language, String country) {
|
|
String l = SystemProperties.get("persist.sys.language");
|
|
String c = SystemProperties.get("persist.sys.country");
|
|
|
|
if (null == language) {
|
|
return; // no match possible
|
|
}
|
|
language = language.toLowerCase();
|
|
if (null == country) {
|
|
country = "";
|
|
}
|
|
country = country.toUpperCase();
|
|
|
|
if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) {
|
|
try {
|
|
// try to find a good match
|
|
String[] locales = mContext.getAssets().getLocales();
|
|
final int N = locales.length;
|
|
String bestMatch = null;
|
|
for(int i = 0; i < N; i++) {
|
|
// only match full (lang + country) locales
|
|
if (locales[i]!=null && locales[i].length() >= 5 &&
|
|
locales[i].substring(0,2).equals(language)) {
|
|
if (locales[i].substring(3,5).equals(country)) {
|
|
bestMatch = locales[i];
|
|
break;
|
|
} else if (null == bestMatch) {
|
|
bestMatch = locales[i];
|
|
}
|
|
}
|
|
}
|
|
if (null != bestMatch) {
|
|
IActivityManager am = ActivityManagerNative.getDefault();
|
|
Configuration config = am.getConfiguration();
|
|
config.locale = new Locale(bestMatch.substring(0,2),
|
|
bestMatch.substring(3,5));
|
|
config.userSetLocale = true;
|
|
am.updateConfiguration(config);
|
|
}
|
|
} catch (Exception e) {
|
|
// Intentionally left blank
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get state
|
|
*/
|
|
public abstract Phone.State getState();
|
|
|
|
/**
|
|
* Retrieves the IccFileHandler of the Phone instance
|
|
*/
|
|
public abstract IccFileHandler getIccFileHandler();
|
|
|
|
/*
|
|
* Retrieves the Handler of the Phone instance
|
|
*/
|
|
public Handler getHandler() {
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Query the status of the CDMA roaming preference
|
|
*/
|
|
public void queryCdmaRoamingPreference(Message response) {
|
|
mCM.queryCdmaRoamingPreference(response);
|
|
}
|
|
|
|
/**
|
|
* Set the status of the CDMA roaming preference
|
|
*/
|
|
public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
|
|
mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
|
|
}
|
|
|
|
/**
|
|
* Set the status of the CDMA subscription mode
|
|
*/
|
|
public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
|
|
mCM.setCdmaSubscription(cdmaSubscriptionType, response);
|
|
}
|
|
|
|
/**
|
|
* Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
|
|
*/
|
|
public void setPreferredNetworkType(int networkType, Message response) {
|
|
mCM.setPreferredNetworkType(networkType, response);
|
|
}
|
|
|
|
public void getPreferredNetworkType(Message response) {
|
|
mCM.getPreferredNetworkType(response);
|
|
}
|
|
|
|
public void getSmscAddress(Message result) {
|
|
mCM.getSmscAddress(result);
|
|
}
|
|
|
|
public void setSmscAddress(String address, Message result) {
|
|
mCM.setSmscAddress(address, result);
|
|
}
|
|
|
|
public void setTTYMode(int ttyMode, Message onComplete) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void queryTTYMode(Message onComplete) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
/**
|
|
* This should only be called in GSM mode.
|
|
* Only here for some backward compatibility
|
|
* issues concerning the GSMPhone class.
|
|
* @deprecated Always returns null.
|
|
*/
|
|
public List<PdpConnection> getCurrentPdpList() {
|
|
return null;
|
|
}
|
|
|
|
public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void getEnhancedVoicePrivacy(Message onComplete) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void setBandMode(int bandMode, Message response) {
|
|
mCM.setBandMode(bandMode, response);
|
|
}
|
|
|
|
public void queryAvailableBandMode(Message response) {
|
|
mCM.queryAvailableBandMode(response);
|
|
}
|
|
|
|
public void invokeOemRilRequestRaw(byte[] data, Message response) {
|
|
mCM.invokeOemRilRequestRaw(data, response);
|
|
}
|
|
|
|
public void invokeOemRilRequestStrings(String[] strings, Message response) {
|
|
mCM.invokeOemRilRequestStrings(strings, response);
|
|
}
|
|
|
|
public void notifyDataActivity() {
|
|
mNotifier.notifyDataActivity(this);
|
|
}
|
|
|
|
public void notifyMessageWaitingIndicator() {
|
|
// This function is added to send the notification to DefaultPhoneNotifier.
|
|
mNotifier.notifyMessageWaitingChanged(this);
|
|
}
|
|
|
|
public void notifyDataConnection(String reason) {
|
|
mNotifier.notifyDataConnection(this, reason);
|
|
}
|
|
|
|
public abstract String getPhoneName();
|
|
|
|
public abstract int getPhoneType();
|
|
|
|
/** @hide */
|
|
public int getVoiceMessageCount(){
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the CDMA ERI icon index to display
|
|
*/
|
|
public int getCdmaEriIconIndex() {
|
|
Log.e(LOG_TAG, "Error! getCdmaEriIconIndex should never be executed in GSM mode");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Returns the CDMA ERI icon mode,
|
|
* 0 - ON
|
|
* 1 - FLASHING
|
|
*/
|
|
public int getCdmaEriIconMode() {
|
|
Log.e(LOG_TAG, "Error! getCdmaEriIconMode should never be executed in GSM mode");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Returns the CDMA ERI text,
|
|
*/
|
|
public String getCdmaEriText() {
|
|
Log.e(LOG_TAG, "Error! getCdmaEriText should never be executed in GSM mode");
|
|
return "GSM nw, no ERI";
|
|
}
|
|
|
|
public String getCdmaMin() {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
return null;
|
|
}
|
|
|
|
public boolean isMinInfoReady() {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
return false;
|
|
}
|
|
|
|
public String getCdmaPrlVersion(){
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
return null;
|
|
}
|
|
|
|
public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void exitEmergencyCallbackMode() {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void unregisterForCdmaOtaStatusChange(Handler h) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void unregisterForSubscriptionInfoReady(Handler h) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public boolean isOtaSpNumber(String dialStr) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
return false;
|
|
}
|
|
|
|
public void registerForCallWaiting(Handler h, int what, Object obj){
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void unregisterForCallWaiting(Handler h){
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void unregisterForEcmTimerReset(Handler h) {
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void registerForSignalInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForSignalInfo(h, what, obj);
|
|
}
|
|
|
|
public void unregisterForSignalInfo(Handler h) {
|
|
mCM.unregisterForSignalInfo(h);
|
|
}
|
|
|
|
public void registerForDisplayInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForDisplayInfo(h, what, obj);
|
|
}
|
|
|
|
public void unregisterForDisplayInfo(Handler h) {
|
|
mCM.unregisterForDisplayInfo(h);
|
|
}
|
|
|
|
public void registerForNumberInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForNumberInfo(h, what, obj);
|
|
}
|
|
|
|
public void unregisterForNumberInfo(Handler h) {
|
|
mCM.unregisterForNumberInfo(h);
|
|
}
|
|
|
|
public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForRedirectedNumberInfo(h, what, obj);
|
|
}
|
|
|
|
public void unregisterForRedirectedNumberInfo(Handler h) {
|
|
mCM.unregisterForRedirectedNumberInfo(h);
|
|
}
|
|
|
|
public void registerForLineControlInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForLineControlInfo( h, what, obj);
|
|
}
|
|
|
|
public void unregisterForLineControlInfo(Handler h) {
|
|
mCM.unregisterForLineControlInfo(h);
|
|
}
|
|
|
|
public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
|
|
mCM.registerFoT53ClirlInfo(h, what, obj);
|
|
}
|
|
|
|
public void unregisterForT53ClirInfo(Handler h) {
|
|
mCM.unregisterForT53ClirInfo(h);
|
|
}
|
|
|
|
public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
|
|
mCM.registerForT53AudioControlInfo( h, what, obj);
|
|
}
|
|
|
|
public void unregisterForT53AudioControlInfo(Handler h) {
|
|
mCM.unregisterForT53AudioControlInfo(h);
|
|
}
|
|
|
|
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public void unsetOnEcbModeExitResponse(Handler h){
|
|
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
|
|
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
|
|
}
|
|
|
|
public String getInterfaceName(String apnType) {
|
|
return mDataConnection.getInterfaceName(apnType);
|
|
}
|
|
|
|
public String getIpAddress(String apnType) {
|
|
return mDataConnection.getIpAddress(apnType);
|
|
}
|
|
|
|
public boolean isDataConnectivityEnabled() {
|
|
return mDataConnection.getDataEnabled();
|
|
}
|
|
|
|
public String getGateway(String apnType) {
|
|
return mDataConnection.getGateway(apnType);
|
|
}
|
|
|
|
public String[] getDnsServers(String apnType) {
|
|
return mDataConnection.getDnsServers(apnType);
|
|
}
|
|
|
|
public String[] getActiveApnTypes() {
|
|
return mDataConnection.getActiveApnTypes();
|
|
}
|
|
|
|
public String getActiveApn() {
|
|
return mDataConnection.getActiveApnString();
|
|
}
|
|
|
|
public int enableApnType(String type) {
|
|
return mDataConnection.enableApnType(type);
|
|
}
|
|
|
|
public int disableApnType(String type) {
|
|
return mDataConnection.disableApnType(type);
|
|
}
|
|
|
|
/**
|
|
* simulateDataConnection
|
|
*
|
|
* simulates various data connection states. This messes with
|
|
* DataConnectionTracker's internal states, but doesn't actually change
|
|
* the underlying radio connection states.
|
|
*
|
|
* @param state Phone.DataState enum.
|
|
*/
|
|
public void simulateDataConnection(Phone.DataState state) {
|
|
DataConnectionTracker.State dcState;
|
|
|
|
switch (state) {
|
|
case CONNECTED:
|
|
dcState = DataConnectionTracker.State.CONNECTED;
|
|
break;
|
|
case SUSPENDED:
|
|
dcState = DataConnectionTracker.State.CONNECTED;
|
|
break;
|
|
case DISCONNECTED:
|
|
dcState = DataConnectionTracker.State.FAILED;
|
|
break;
|
|
default:
|
|
dcState = DataConnectionTracker.State.CONNECTING;
|
|
break;
|
|
}
|
|
|
|
mDataConnection.setState(dcState);
|
|
notifyDataConnection(null);
|
|
}
|
|
|
|
/**
|
|
* Notifiy registrants of a new ringing Connection.
|
|
* Subclasses of Phone probably want to replace this with a
|
|
* version scoped to their packages
|
|
*/
|
|
protected void notifyNewRingingConnectionP(Connection cn) {
|
|
AsyncResult ar = new AsyncResult(null, cn, null);
|
|
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
|
|
}
|
|
|
|
/**
|
|
* Notify registrants of a RING event.
|
|
*/
|
|
private void notifyIncomingRing() {
|
|
AsyncResult ar = new AsyncResult(null, this, null);
|
|
mIncomingRingRegistrants.notifyRegistrants(ar);
|
|
}
|
|
|
|
/**
|
|
* Send the incoming call Ring notification if conditions are right.
|
|
*/
|
|
private void sendIncomingCallRingNotification(int token) {
|
|
if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) {
|
|
Log.d(LOG_TAG, "Sending notifyIncomingRing");
|
|
notifyIncomingRing();
|
|
sendMessageDelayed(
|
|
obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
|
|
} else {
|
|
Log.d(LOG_TAG, "Ignoring ring notification request,"
|
|
+ " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
|
|
+ " token=" + token
|
|
+ " mCallRingContinueToken=" + mCallRingContinueToken);
|
|
}
|
|
}
|
|
}
|