diff --git a/Android.mk b/Android.mk index 449faa00a6..06b7419615 100644 --- a/Android.mk +++ b/Android.mk @@ -24,6 +24,10 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src/java) \ $(call all-Iaidl-files-under, src/java) \ $(call all-logtags-files-under, src/java) +ifneq ($(BOARD_RIL_CLASS),) +LOCAL_SRC_FILES += $(call find-other-java-files,$(BOARD_RIL_CLASS)) +endif + LOCAL_JAVA_LIBRARIES := voip-common ims-common LOCAL_MODULE_TAGS := optional LOCAL_MODULE := telephony-common diff --git a/src/java/com/android/internal/telephony/BlacklistUtils.java b/src/java/com/android/internal/telephony/BlacklistUtils.java new file mode 100644 index 0000000000..ecb971715d --- /dev/null +++ b/src/java/com/android/internal/telephony/BlacklistUtils.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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.util; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.UserHandle; +import android.provider.Settings; +import android.provider.Telephony.Blacklist; +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +import com.android.internal.telephony.CallerInfo; + +/** + * Blacklist Utility Class + * @hide + */ +public class BlacklistUtils { + private static final String TAG = "BlacklistUtils"; + private static final boolean DEBUG = false; + + // Blacklist matching type + public final static int MATCH_NONE = 0; + public final static int MATCH_PRIVATE = 1; + public final static int MATCH_UNKNOWN = 2; + public final static int MATCH_LIST = 3; + public final static int MATCH_REGEX = 4; + + public final static int BLOCK_CALLS = + Settings.System.BLACKLIST_BLOCK << Settings.System.BLACKLIST_PHONE_SHIFT; + public final static int BLOCK_MESSAGES = + Settings.System.BLACKLIST_BLOCK << Settings.System.BLACKLIST_MESSAGE_SHIFT; + + public static boolean addOrUpdate(Context context, String number, int flags, int valid) { + ContentValues cv = new ContentValues(); + + if ((valid & BLOCK_CALLS) != 0) { + cv.put(Blacklist.PHONE_MODE, (flags & BLOCK_CALLS) != 0 ? 1 : 0); + } + if ((valid & BLOCK_MESSAGES) != 0) { + cv.put(Blacklist.MESSAGE_MODE, (flags & BLOCK_MESSAGES) != 0 ? 1 : 0); + } + + Uri uri = Uri.withAppendedPath(Blacklist.CONTENT_FILTER_BYNUMBER_URI, number); + int count = context.getContentResolver().update(uri, cv, null, null); + + return count > 0; + } + + /** + * Check if the number is in the blacklist + * @param number: Number to check + * @return one of: MATCH_NONE, MATCH_PRIVATE, MATCH_UNKNOWN, MATCH_LIST or MATCH_REGEX + */ + public static int isListed(Context context, String number, int mode) { + if (!isBlacklistEnabled(context)) { + return MATCH_NONE; + } + + if (DEBUG) { + Log.d(TAG, "Checking number " + number + " against the Blacklist for mode " + mode); + } + + final String type; + + if (mode == BLOCK_CALLS) { + if (DEBUG) Log.d(TAG, "Checking if an incoming call should be blocked"); + type = Blacklist.PHONE_MODE; + } else if (mode == BLOCK_MESSAGES) { + if (DEBUG) Log.d(TAG, "Checking if an incoming message should be blocked"); + type = Blacklist.MESSAGE_MODE; + } else { + Log.e(TAG, "Invalid mode " + mode); + return MATCH_NONE; + } + + // Private and unknown number matching + if (TextUtils.isEmpty(number)) { + if (isBlacklistPrivateNumberEnabled(context, mode)) { + return MATCH_PRIVATE; + } + return MATCH_NONE; + } + + if (isBlacklistUnknownNumberEnabled(context, mode)) { + CallerInfo ci = CallerInfo.getCallerInfo(context, number); + if (!ci.contactExists) { + return MATCH_UNKNOWN; + } + } + + Uri.Builder builder = Blacklist.CONTENT_FILTER_BYNUMBER_URI.buildUpon(); + builder.appendPath(number); + if (isBlacklistRegexEnabled(context)) { + builder.appendQueryParameter(Blacklist.REGEX_KEY, "1"); + } + + int result = MATCH_NONE; + Cursor c = context.getContentResolver().query(builder.build(), + new String[] { Blacklist.IS_REGEX, type }, null, null, null); + + if (c != null) { + if (DEBUG) Log.d(TAG, "Blacklist query successful, " + c.getCount() + " matches"); + int regexColumnIndex = c.getColumnIndexOrThrow(Blacklist.IS_REGEX); + int modeColumnIndex = c.getColumnIndexOrThrow(type); + boolean whitelisted = false; + + c.moveToPosition(-1); + while (c.moveToNext()) { + boolean isRegex = c.getInt(regexColumnIndex) != 0; + boolean blocked = c.getInt(modeColumnIndex) != 0; + + if (!isRegex) { + whitelisted = !blocked; + result = MATCH_LIST; + if (blocked) { + break; + } + } else if (blocked) { + result = MATCH_REGEX; + } + } + if (whitelisted) { + result = MATCH_NONE; + } + c.close(); + } + + return result; + } + + public static boolean isBlacklistEnabled(Context context) { + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.PHONE_BLACKLIST_ENABLED, 1, + UserHandle.USER_CURRENT_OR_SELF) != 0; + } + + public static boolean isBlacklistNotifyEnabled(Context context) { + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.PHONE_BLACKLIST_NOTIFY_ENABLED, 1, + UserHandle.USER_CURRENT_OR_SELF) != 0; + } + + public static boolean isBlacklistPrivateNumberEnabled(Context context, int mode) { + return (Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.PHONE_BLACKLIST_PRIVATE_NUMBER_MODE, 0, + UserHandle.USER_CURRENT_OR_SELF) & mode) != 0; + } + + public static boolean isBlacklistUnknownNumberEnabled(Context context, int mode) { + return (Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.PHONE_BLACKLIST_UNKNOWN_NUMBER_MODE, 0, + UserHandle.USER_CURRENT_OR_SELF) & mode) != 0; + } + + public static boolean isBlacklistRegexEnabled(Context context) { + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.PHONE_BLACKLIST_REGEX_ENABLED, 0, + UserHandle.USER_CURRENT_OR_SELF) != 0; + } +} diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java index ea34c8ca85..06887f88ec 100644 --- a/src/java/com/android/internal/telephony/CommandsInterface.java +++ b/src/java/com/android/internal/telephony/CommandsInterface.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -113,11 +114,11 @@ public boolean isAvailable() { /** * response.obj.result is an int[2] * - * response.obj.result[0] is IMS registration state + * response.obj.result[0] is registration state * 0 - Not registered * 1 - Registered - * response.obj.result[1] is of type RILConstants.GSM_PHONE or - * RILConstants.CDMA_PHONE + * response.obj.result[1] is of type const RIL_IMS_SMS_Format, + * corresponds to sms format used for SMS over IMS. */ void getImsRegistrationState(Message result); @@ -643,6 +644,7 @@ public boolean isAvailable() { * * AID (Application ID), See ETSI 102.221 8.1 and 101.220 4 * + * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * This exception is CommandException with an error of PASSWORD_INCORRECT @@ -1327,12 +1329,18 @@ void setFacilityLockForApp(String facility, boolean lockState, String password, * Query the list of band mode supported by RF. * * @param response is callback message - * ((AsyncResult)response.obj).result is an int[] where int[0] is + * ((AsyncResult)response.obj).result is an int[] with every * the size of the array and the rest of each element representing - * one available BM_*_BAND + * element representing one avialable BM_*_BAND */ void queryAvailableBandMode (Message response); + /** + * Set the current preferred network type. This will be the last + * networkType that was passed to setPreferredNetworkType. + */ + void setCurrentPreferredNetworkType(); + /** * Requests to set the preferred network type for searching and registering * (CS/PS domain, RAT, and operation mode) @@ -1703,11 +1711,11 @@ public void setupDataCall(String radioTechnology, String profile, * Sets the minimum time in milli-seconds between when RIL_UNSOL_CELL_INFO_LIST * should be invoked. * - * The default, 0, means invoke RIL_UNSOL_CELL_INFO_LIST when any of the reported + * The default, 0, means invoke RIL_UNSOL_CELL_INFO_LIST when any of the reported * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue * A RIL_UNSOL_CELL_INFO_LIST. * - * + * * @param rateInMillis is sent back to handler and result.obj is a AsyncResult * @param response.obj is AsyncResult ar when sent to associated handler diff --git a/src/java/com/android/internal/telephony/HTCQualcommM7CDMARIL.java b/src/java/com/android/internal/telephony/HTCQualcommM7CDMARIL.java new file mode 100644 index 0000000000..ab29a8d5f1 --- /dev/null +++ b/src/java/com/android/internal/telephony/HTCQualcommM7CDMARIL.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2013 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 static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.os.Parcel; +import android.provider.Settings; +import android.telephony.CellInfo; + +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.uicc.IccCardStatus; + +public class HTCQualcommM7CDMARIL extends RIL implements CommandsInterface { + + static final int RIL_UNSOL_ENTER_LPM_M7 = 3023; + static final int RIL_UNSOL_CDMA_3G_INDICATOR_M7 = 4259; + static final int RIL_UNSOL_CDMA_ENHANCE_ROAMING_INDICATOR_M7 = 4262; + static final int RIL_UNSOL_CDMA_NETWORK_BASE_PLUSCODE_DIAL_M7 = 4270; + static final int RIL_UNSOL_RESPONSE_PHONE_MODE_CHANGE_M7 = 4802; + static final int RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED_HTC_M7 = 5755; + static final int RIL_UNSOL_RESPONSE_DATA_NETWORK_STATE_CHANGED_M7 = 5757; + + public HTCQualcommM7CDMARIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @Override + protected Object + responseIccCardStatus(Parcel p) { + IccCardApplicationStatus appStatus; + + IccCardStatus cardStatus = new IccCardStatus(); + cardStatus.setCardState(p.readInt()); + cardStatus.setUniversalPinState(p.readInt()); + cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt(); + cardStatus.mCdmaSubscriptionAppIndex = p.readInt(); + cardStatus.mImsSubscriptionAppIndex = p.readInt(); + + int numApplications = p.readInt(); + + // limit to maximum allowed applications + if (numApplications > IccCardStatus.CARD_MAX_APPS) { + numApplications = IccCardStatus.CARD_MAX_APPS; + } + cardStatus.mApplications = new IccCardApplicationStatus[numApplications]; + if (numApplications == 1) { + cardStatus.mApplications = new IccCardApplicationStatus[numApplications + 2]; + } + appStatus = new IccCardApplicationStatus(); + for (int i = 0 ; i < numApplications ; i++) { + appStatus = new IccCardApplicationStatus(); + appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt()); + appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt()); + appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt()); + appStatus.aid = p.readString(); + appStatus.app_label = p.readString(); + appStatus.pin1_replaced = p.readInt(); + appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt()); + appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt()); + cardStatus.mApplications[i] = appStatus; + } + if (numApplications == 1) { + cardStatus.mCdmaSubscriptionAppIndex = 1; + cardStatus.mImsSubscriptionAppIndex = 2; + IccCardApplicationStatus appStatus2 = new IccCardApplicationStatus(); + appStatus2.app_type = appStatus2.AppTypeFromRILInt(4); // csim state + appStatus2.app_state = appStatus.app_state; + appStatus2.perso_substate = appStatus.perso_substate; + appStatus2.aid = appStatus.aid; + appStatus2.app_label = appStatus.app_label; + appStatus2.pin1_replaced = appStatus.pin1_replaced; + appStatus2.pin1 = appStatus.pin1; + appStatus2.pin2 = appStatus.pin2; + cardStatus.mApplications[cardStatus.mCdmaSubscriptionAppIndex] = appStatus2; + IccCardApplicationStatus appStatus3 = new IccCardApplicationStatus(); + appStatus3.app_type = appStatus3.AppTypeFromRILInt(5); // ims state + appStatus3.app_state = appStatus.app_state; + appStatus3.perso_substate = appStatus.perso_substate; + appStatus3.aid = appStatus.aid; + appStatus3.app_label = appStatus.app_label; + appStatus3.pin1_replaced = appStatus.pin1_replaced; + appStatus3.pin1 = appStatus.pin1; + appStatus3.pin2 = appStatus.pin2; + cardStatus.mApplications[cardStatus.mImsSubscriptionAppIndex] = appStatus3; + } + // get type from Settings.Global default to CDMA + LTE network mode + boolean forceCdmaLte = needsOldRilFeature("forceCdmaLteNetworkType"); + if (forceCdmaLte) { + int phoneType = android.provider.Settings.Global.getInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE, + NETWORK_MODE_LTE_CDMA_EVDO); + setPreferredNetworkType(phoneType, null); + } + return cardStatus; + } + + @Override + protected void + processUnsolicited(Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + switch (response) { + case RIL_UNSOL_ENTER_LPM_M7: ret = responseVoid(p); break; + case RIL_UNSOL_CDMA_3G_INDICATOR_M7: ret = responseInts(p); break; + case RIL_UNSOL_CDMA_ENHANCE_ROAMING_INDICATOR_M7: ret = responseInts(p); break; + case RIL_UNSOL_CDMA_NETWORK_BASE_PLUSCODE_DIAL_M7: ret = responseStrings(p); break; + case RIL_UNSOL_RESPONSE_PHONE_MODE_CHANGE_M7: ret = responseInts(p); break; + case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED_HTC_M7: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_DATA_NETWORK_STATE_CHANGED_M7: ret = responseInts(p); break; + case RIL_UNSOL_RIL_CONNECTED: + ret = responseInts(p); + + // Initial conditions + setRadioPower(false, null); + setPreferredNetworkType(mPreferredNetworkType, null); + int cdmaSubscription = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.CDMA_SUBSCRIPTION_MODE, -1); + if (cdmaSubscription != -1) { + setCdmaSubscriptionSource(cdmaSubscription, null); + } + setCellInfoListRate(Integer.MAX_VALUE, null); + notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); + break; + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + } +} diff --git a/src/java/com/android/internal/telephony/Operators.java b/src/java/com/android/internal/telephony/Operators.java new file mode 100644 index 0000000000..6de45dec2c --- /dev/null +++ b/src/java/com/android/internal/telephony/Operators.java @@ -0,0 +1,1532 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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 java.util.Collections; +import java.util.Map; +import java.util.HashMap; + +public class Operators{ + + private static Map operators = null; + + // Initialize list of Operator codes + private static void initList() { + // Setting capacity to 1489 and load factor to 1. + // Rehashes won't happen during initialization. + // Change the initial capacity if more carriers are added. + Map init = new HashMap(1489,1); + init.put("41201","AWCC"); /*Afghanistan*/ + init.put("41240","Areeba"); /*Afghanistan*/ + init.put("41250","Etisalat"); /*Afghanistan*/ + init.put("41220","Roshan"); /*Afghanistan*/ + init.put("27601","AMC"); /*Albania*/ + init.put("27603","Eagle Mobile"); /*Albania*/ + init.put("27604","Plus Communication"); /*Albania*/ + init.put("27602","Vodafone"); /*Albania*/ + init.put("60302","Djezzy"); /*Algeria*/ + init.put("60301","Mobilis"); /*Algeria*/ + init.put("60303","Nedjma"); /*Algeria*/ + init.put("54411","Bluesky"); /*American Samoa*/ + init.put("21303","Mobiland"); /*Andorra*/ + init.put("63104","MOVICEL"); /*Angola*/ + init.put("63102","UNITEL"); /*Angola*/ + init.put("365840","Cable & Wireless"); /*Anguilla (United Kingdom)*/ + init.put("365010","Weblinks Limited"); /*Anguilla (United Kingdom)*/ + init.put("344030","APUA"); /*Antigua and Barbuda*/ + init.put("344920","bmobile"); /*Antigua and Barbuda*/ + init.put("344930","Digicel"); /*Antigua and Barbuda*/ + init.put("722310","Claro"); /*Argentina*/ + init.put("722320","Claro"); /*Argentina*/ + init.put("722330","Claro"); /*Argentina*/ + init.put("722350","Hutchinson (PORT HABLE)"); /*Argentina*/ + init.put("722010","Movistar"); /*Argentina*/ + init.put("722070","Movistar"); /*Argentina*/ + init.put("722020","Nextel"); /*Argentina*/ + init.put("72234","Personal"); /*Argentina*/ + init.put("722341","Telecom Personal SA"); /*Argentina*/ + init.put("72236","Telecom Personal SA"); /*Argentina*/ + init.put("28301","Beeline"); /*Armenia*/ + init.put("28310","Orange"); /*Armenia*/ + init.put("28305","VivaCell-MTS"); /*Armenia*/ + init.put("36302","Digicel"); /*Aruba (Netherlands)*/ + init.put("36320","Digicell"); /*Aruba (Netherlands)*/ + init.put("36301","SETAR"); /*Aruba (Netherlands)*/ + init.put("50506","3"); /*Australia*/ + init.put("50512","3"); /*Australia*/ + init.put("50515","3GIS"); /*Australia*/ + init.put("50514","AAPT"); /*Australia*/ + init.put("50524","Advanced Communications Technologies"); /*Australia*/ + init.put("50509","Airnet"); /*Australia*/ + init.put("50538","Crazy John's"); /*Australia*/ + init.put("50504","Department of Defence"); /*Australia*/ + init.put("50588","Localstar"); /*Australia*/ + init.put("50510","Norfolk Telecom"); /*Australia*/ + init.put("50508","One. Tel"); /*Australia*/ + init.put("50599","One. Tel"); /*Australia*/ + init.put("50502","OPTUS / Virgin Mobile"); /*Australia*/ + init.put("50505","Ozitel"); /*Australia*/ + init.put("50513","Railcorp"); /*Australia*/ + init.put("50521","SOUL"); /*Australia*/ + init.put("50501","Telstra"); /*Australia*/ + init.put("50511","Telstra"); /*Australia*/ + init.put("50571","Telstra"); /*Australia*/ + init.put("50572","Telstra"); /*Australia*/ + init.put("50516","Victorian Rail Track"); /*Australia*/ + init.put("50503","Vodafone"); /*Australia*/ + init.put("50507","Vodafone"); /*Australia*/ + init.put("50590","YES OPTUS"); /*Australia*/ + init.put("23210","3"); /*Austria*/ + init.put("23214","3"); /*Austria*/ + init.put("23201","A1"); /*Austria*/ + init.put("23209","A1"); /*Austria*/ + init.put("23215","Barablu"); /*Austria*/ + init.put("23211","bob"); /*Austria*/ + init.put("23291","GSM-R A"); /*Austria*/ + init.put("23205","Orange"); /*Austria*/ + init.put("23203","T-Mobile"); /*Austria*/ + init.put("23207","T-Mobile"); /*Austria*/ + init.put("23212","yesss"); /*Austria*/ + init.put("40001","Azercell"); /*Azerbaijan*/ + init.put("40002","Bakcell"); /*Azerbaijan*/ + init.put("40003","FONEX"); /*Azerbaijan*/ + init.put("40004","Nar Mobile"); /*Azerbaijan*/ + init.put("364390","BaTelCo"); /*Bahamas*/ + init.put("42601","Batelco"); /*Bahrain*/ + init.put("42602","MTC-VFBH"); /*Bahrain*/ + init.put("42604","VIVA"); /*Bahrain*/ + init.put("47002","Aktel"); /*Bangladesh*/ + init.put("47003","Banglalink"); /*Bangladesh*/ + init.put("47005","Citycell"); /*Bangladesh*/ + init.put("47006","Citycell"); /*Bangladesh*/ + init.put("47001","Grameenphone"); /*Bangladesh*/ + init.put("47004","TeleTalk"); /*Bangladesh*/ + init.put("47007","Warid"); /*Bangladesh*/ + init.put("342600","bmobile"); /*Barbados*/ + init.put("342750","Digicel"); /*Barbados*/ + init.put("342820","Sunbeach Communications"); /*Barbados*/ + init.put("257501","BelCel JV"); /*Belarus*/ + init.put("25703","DIALLOG"); /*Belarus*/ + init.put("25704","life:)"); /*Belarus*/ + init.put("25702","MTS"); /*Belarus*/ + init.put("25701","Velcom"); /*Belarus*/ + init.put("20620","BASE"); /*Belgium*/ + init.put("20610","Mobistar"); /*Belgium*/ + init.put("20601","Proximus"); /*Belgium*/ + init.put("20605","Telenet"); /*Belgium*/ + init.put("70267","Belize Telemedia"); /*Belize*/ + init.put("70268","International Telecommunications Ltd."); /*Belize*/ + init.put("70299","Smart"); /*Belize*/ + init.put("61603","Areeba"); /*Benin*/ + init.put("61600","BBCOM"); /*Benin*/ + init.put("61604","BBCOM"); /*Benin*/ + init.put("61605","Glo"); /*Benin*/ + init.put("61601","Libercom"); /*Benin*/ + init.put("61602","Telecel"); /*Benin*/ + init.put("31038","Digicel"); /*Bermudas*/ + init.put("35001","Digicel Bermuda"); /*Bermudas*/ + init.put("35002","Mobility"); /*Bermudas*/ + init.put("40211","B-Mobile"); /*Bhutan*/ + init.put("40277","TashiCell"); /*Bhutan*/ + init.put("73602","Entel"); /*Bolivia*/ + init.put("73601","Nuevatel"); /*Bolivia*/ + init.put("73603","Tigo"); /*Bolivia*/ + init.put("21890","BH Mobile"); /*Bosnia and Herzegovina*/ + init.put("21803","ERONET"); /*Bosnia and Herzegovina*/ + init.put("21805","m:tel"); /*Bosnia and Herzegovina*/ + init.put("65204","BTC Mobile"); /*Botswana*/ + init.put("65201","Mascom"); /*Botswana*/ + init.put("65202","Orange"); /*Botswana*/ + init.put("72437","aiou"); /*Brazil*/ + init.put("72424","Amazonia Celular"); /*Brazil*/ + init.put("72416","Brasil Telecom"); /*Brazil*/ + init.put("72405","Claro"); /*Brazil*/ + init.put("72432","CTBC Cellular"); /*Brazil*/ + init.put("72433","CTBC Cellular"); /*Brazil*/ + init.put("72434","CTBC Cellular"); /*Brazil*/ + init.put("72407","CTBC Celular"); /*Brazil*/ + init.put("72400","Nextel"); /*Brazil*/ + init.put("72439","Nextel"); /*Brazil*/ + init.put("72415","Sercomtel"); /*Brazil*/ + init.put("72402","TIM"); /*Brazil*/ + init.put("72403","TIM"); /*Brazil*/ + init.put("72404","TIM"); /*Brazil*/ + init.put("72408","TIM"); /*Brazil*/ + init.put("72431","TNL PCS"); /*Brazil*/ + init.put("72406","Vivo"); /*Brazil*/ + init.put("72410","Vivo"); /*Brazil*/ + init.put("72411","Vivo"); /*Brazil*/ + init.put("72423","Vivo"); /*Brazil*/ + init.put("348170","Cable & Wireless"); /*British Virgin Islands (United Kingdom)*/ + init.put("348570","Caribbean Cellular Telephone"); /*British Virgin Islands (United Kingdom)*/ + init.put("348770","Digicel"); /*British Virgin Islands (United Kingdom)*/ + init.put("52802","B-Mobile"); /*Brunei*/ + init.put("52811","DTSCom"); /*Brunei*/ + init.put("52801","Jabatan Telekom"); /*Brunei*/ + init.put("28405","GLOBUL"); /*Bulgaria*/ + init.put("28401","M-Tel"); /*Bulgaria*/ + init.put("28404","Undisclosed"); /*Bulgaria*/ + init.put("28403","Vivatel"); /*Bulgaria*/ + init.put("61301","Onatel"); /*Burkina Faso*/ + init.put("61303","Telecel Faso"); /*Burkina Faso*/ + init.put("61302","Zain"); /*Burkina Faso*/ + init.put("64202","Africell"); /*Burundi*/ + init.put("64208","HiTs Telecom"); /*Burundi*/ + init.put("64207","Smart Mobile"); /*Burundi*/ + init.put("64201","Spacetel"); /*Burundi*/ + init.put("64203","Telecel"); /*Burundi*/ + init.put("64282","U-COM Burundi"); /*Burundi*/ + init.put("45609","Beeline"); /*Cambodia*/ + init.put("45618","Camshin / Shinawatra"); /*Cambodia*/ + init.put("45611","Excell"); /*Cambodia*/ + init.put("45602","hello"); /*Cambodia*/ + init.put("45608","Metfone"); /*Cambodia*/ + init.put("45601","Mobitel"); /*Cambodia*/ + init.put("45604","qb"); /*Cambodia*/ + init.put("45603","S Telecom"); /*Cambodia*/ + init.put("45606","Smart Mobile"); /*Cambodia*/ + init.put("45605","Star-Cell"); /*Cambodia*/ + init.put("62401","MTN Cameroon"); /*Cameroon*/ + init.put("62402","Orange"); /*Cameroon*/ + init.put("302290","Airtel Wireless"); /*Canada*/ + init.put("302652","BC Tel Mobility"); /*Canada*/ + init.put("302610","Bell"); /*Canada*/ + init.put("302640","Bell"); /*Canada*/ + init.put("302880","Bell / Telus / SaskTel"); /*Canada*/ + init.put("302651","Bell Mobility"); /*Canada*/ + init.put("302380","DMTS"); /*Canada*/ + init.put("302370","Fido"); /*Canada*/ + init.put("302350","FIRST"); /*Canada*/ + init.put("302710","Globalstar"); /*Canada*/ + init.put("302620","ICE Wireless"); /*Canada*/ + init.put("302701","MB Tel Mobility"); /*Canada*/ + init.put("302320","Mobilicity"); /*Canada*/ + init.put("302702","MT&T Mobility"); /*Canada*/ + init.put("302660","MTS"); /*Canada*/ + init.put("302655","MTS Mobility"); /*Canada*/ + init.put("302703","New Tel Mobility"); /*Canada*/ + init.put("302720","Rogers Wireless"); /*Canada*/ + init.put("302654","Sask Tel Mobility"); /*Canada*/ + init.put("302680","SaskTel"); /*Canada*/ + init.put("302780","SaskTel"); /*Canada*/ + init.put("302656","Tbay Mobility"); /*Canada*/ + init.put("302220","Telus"); /*Canada*/ + init.put("302221","Telus"); /*Canada*/ + init.put("302657","Telus (Quebec) Mobility"); /*Canada*/ + init.put("302360","Telus Mobility"); /*Canada*/ + init.put("302361","Telus Mobility"); /*Canada*/ + init.put("302653","Telus Mobility"); /*Canada*/ + init.put("302500","Videotron"); /*Canada*/ + init.put("302510","Videotron"); /*Canada*/ + init.put("302490","WIND Mobile"); /*Canada*/ + init.put("62501","CVMOVEL"); /*Cape Verde*/ + init.put("62502","T+"); /*Cape Verde*/ + init.put("346140","Cable & Wireless"); /*Cayman Islands (United Kingdom)*/ + init.put("346050","Digicel"); /*Cayman Islands (United Kingdom)*/ + init.put("62301","CTP"); /*Central African Republic*/ + init.put("62304","Nationlink"); /*Central African Republic*/ + init.put("62303","Orange"); /*Central African Republic*/ + init.put("62302","TC"); /*Central African Republic*/ + init.put("73003","Claro"); /*Chile*/ + init.put("73001","Entel"); /*Chile*/ + init.put("73010","Entel"); /*Chile*/ + init.put("73002","movistar"); /*Chile*/ + init.put("73004","Nextel"); /*Chile*/ + init.put("73008","VTR MOvil"); /*Chile*/ + init.put("73099","Will"); /*Chile*/ + init.put("46006","(unknown)"); /*China*/ + init.put("46000","China Mobile"); /*China*/ + init.put("46002","China Mobile"); /*China*/ + init.put("46007","China Mobile"); /*China*/ + init.put("46003","China Telecom"); /*China*/ + init.put("46005","China Telecom"); /*China*/ + init.put("46020","China Tietong"); /*China*/ + init.put("46001","China Unicom"); /*China*/ + init.put("732001","Colombia Telecomunicaciones S.A. - Telecom"); /*Colombia*/ + init.put("732101","Comcel"); /*Colombia*/ + init.put("732002","Edatel"); /*Colombia*/ + init.put("732102","movistar"); /*Colombia*/ + init.put("732123","movistar"); /*Colombia*/ + init.put("732103","Tigo"); /*Colombia*/ + init.put("732111","Tigo"); /*Colombia*/ + init.put("65401","HURI - SNPT"); /*Comoros*/ + init.put("54801","Telecom Cook"); /*Cook Islands*/ + init.put("71201","ICE"); /*Costa Rica*/ + init.put("71202","ICE"); /*Costa Rica*/ + init.put("71203","ICE"); /*Costa Rica*/ + init.put("71204","movistar"); /*Costa Rica*/ + init.put("61201","Cora de Comstar"); /*Cote d'Ivoire*/ + init.put("61204","KoZ"); /*Cote d'Ivoire*/ + init.put("61202","Moov"); /*Cote d'Ivoire*/ + init.put("61205","MTN"); /*Cote d'Ivoire*/ + init.put("61203","Orange"); /*Cote d'Ivoire*/ + init.put("61206","ORICEL"); /*Cote d'Ivoire*/ + init.put("21901","T-Mobile"); /*Croatia*/ + init.put("21902","Tele2"); /*Croatia*/ + init.put("21910","VIPnet"); /*Croatia*/ + init.put("36801","ETECSA"); /*Cuba*/ + init.put("28001","Cytamobile-Vodafone"); /*Cyprus*/ + init.put("28010","MTN"); /*Cyprus*/ + init.put("62204","Salam"); /*Czad*/ + init.put("62202","TAWALI"); /*Czad*/ + init.put("62203","TIGO - Millicom"); /*Czad*/ + init.put("62201","Zain"); /*Czad*/ + init.put("23002","EUROTEL PRAHA"); /*Czech Republic*/ + init.put("23003","OSKAR"); /*Czech Republic*/ + init.put("23006","OSNO TELECOMUNICATION, s.r.o."); /*Czech Republic*/ + init.put("23098","SeDC s.o."); /*Czech Republic*/ + init.put("23001","T-Mobile"); /*Czech Republic*/ + init.put("23005","TRAVEL TELEKOMMUNIKATION, s.r.o."); /*Czech Republic*/ + init.put("23004","U:fon"); /*Czech Republic*/ + init.put("23099","Vodafone Czech Republic a.s., R&D Centre at FEE, CTU"); /*Czech Republic*/ + init.put("63086","CCT"); /*Democratic Republic of Congo*/ + init.put("63004","Cellco"); /*Democratic Republic of Congo*/ + init.put("63010","Libertis Telecom"); /*Democratic Republic of Congo*/ + init.put("63089","SAIT Telecom"); /*Democratic Republic of Congo*/ + init.put("63005","Supercell"); /*Democratic Republic of Congo*/ + init.put("63001","Vodacom"); /*Democratic Republic of Congo*/ + init.put("63002","Zain"); /*Democratic Republic of Congo*/ + init.put("23806","3"); /*Denmark*/ + init.put("23805","ApS KBUS"); /*Denmark*/ + init.put("23807","Barablu Mobile Ltd."); /*Denmark*/ + init.put("23809","Dansk Beredskabskommunikation A/S"); /*Denmark*/ + init.put("23811","Dansk Beredskabskommunikation A/S"); /*Denmark*/ + init.put("23840","Ericsson Danmark A/S"); /*Denmark*/ + init.put("23812","Lycamobile Denmark Ltd"); /*Denmark*/ + init.put("23803","MIGway A/S"); /*Denmark*/ + init.put("23877","Sonofon"); /*Denmark*/ + init.put("23801","TDC"); /*Denmark*/ + init.put("23810","TDC"); /*Denmark*/ + init.put("23802","Telenor"); /*Denmark*/ + init.put("23820","Telia"); /*Denmark*/ + init.put("23830","Telia"); /*Denmark*/ + init.put("63801","Evatis"); /*Djibouti*/ + init.put("366110","Cable & Wireless"); /*Dominica*/ + init.put("366020","Digicel"); /*Dominica*/ + init.put("37002","Claro"); /*Dominican Republic*/ + init.put("37001","Orange"); /*Dominican Republic*/ + init.put("37003","Tricom S.A."); /*Dominican Republic*/ + init.put("37004","ViVa"); /*Dominican Republic*/ + init.put("51402","Timor Telecom"); /*East Timor*/ + init.put("74002","Alegro"); /*Ecuador*/ + init.put("74000","Movistar"); /*Ecuador*/ + init.put("74001","Porta"); /*Ecuador*/ + init.put("60203","Etisalat"); /*Egypt*/ + init.put("60201","Mobinil"); /*Egypt*/ + init.put("60202","Vodafone"); /*Egypt*/ + init.put("70610","Claro"); /*El Salvador*/ + init.put("70611","Claro"); /*El Salvador*/ + init.put("70601","CTE Telecom Personal"); /*El Salvador*/ + init.put("70602","digicel"); /*El Salvador*/ + init.put("70604","movistar"); /*El Salvador*/ + init.put("70603","Telemovil EL Salvador"); /*El Salvador*/ + init.put("62703","Hits GQ"); /*Equatorial Guinea*/ + init.put("62701","Orange GQ"); /*Equatorial Guinea*/ + init.put("65701","Eritel"); /*Eritrea*/ + init.put("24805","AS Bravocom Mobiil"); /*Estonia*/ + init.put("24802","Elisa"); /*Estonia*/ + init.put("24801","EMT"); /*Estonia*/ + init.put("24804","OY Top Connect"); /*Estonia*/ + init.put("24806","OY ViaTel"); /*Estonia*/ + init.put("24803","Tele 2"); /*Estonia*/ + init.put("63601","ETMTN"); /*Ethiopia*/ + init.put("28801","Faroese Telecom"); /*Faroe Islands (Denmark)*/ + init.put("28802","Vodafone"); /*Faroe Islands (Denmark)*/ + init.put("54202","Digicel"); /*Fiji*/ + init.put("54201","Vodafone"); /*Fiji*/ + init.put("24414","AMT"); /*Finland*/ + init.put("24403","DNA"); /*Finland*/ + init.put("24412","DNA"); /*Finland*/ + init.put("24405","Elisa"); /*Finland*/ + init.put("24407","Nokia"); /*Finland*/ + init.put("24415","SAMK"); /*Finland*/ + init.put("24421","Saunalahti"); /*Finland*/ + init.put("24429","Scnl Truphone"); /*Finland*/ + init.put("24491","Sonera"); /*Finland*/ + init.put("24410","TDC Oy"); /*Finland*/ + init.put("24408","Unknown"); /*Finland*/ + init.put("24411","VIRVE"); /*Finland*/ + init.put("20820","Bouygues"); /*France*/ + init.put("20821","Bouygues"); /*France*/ + init.put("20888","Bouygues"); /*France*/ + init.put("20801","France Telecom Mobile"); /*France*/ + init.put("20814","Free Mobile"); /*France*/ + init.put("20815","Free Mobile"); /*France*/ + init.put("20805","Globalstar Europe"); /*France*/ + init.put("20806","Globalstar Europe"); /*France*/ + init.put("20807","Globalstar Europe"); /*France*/ + init.put("20800","Orange"); /*France*/ + init.put("20802","Orange"); /*France*/ + init.put("20810","SFR"); /*France*/ + init.put("20811","SFR"); /*France*/ + init.put("20813","SFR"); /*France*/ + init.put("20822","Transatel Mobile"); /*France*/ + init.put("54720","VINI"); /*French Polynesia (France)*/ + init.put("62804","Azur"); /*Gabon*/ + init.put("62801","Libertis"); /*Gabon*/ + init.put("62802","Moov (Telecel) Gabon S.A."); /*Gabon*/ + init.put("62803","Zain"); /*Gabon*/ + init.put("60702","Africel"); /*Gambia*/ + init.put("60703","Comium"); /*Gambia*/ + init.put("60701","Gamcel"); /*Gambia*/ + init.put("60704","QCell"); /*Gambia*/ + init.put("28988","A-Mobile"); /*Georgia*/ + init.put("28967","Aquafon"); /*Georgia*/ + init.put("28204","Beeline"); /*Georgia*/ + init.put("28201","Geocell"); /*Georgia*/ + init.put("28203","Iberiatel"); /*Georgia*/ + init.put("28202","Magti"); /*Georgia*/ + init.put("28205","Silknet"); /*Georgia*/ + init.put("26242","27C3"); /*Germany*/ + init.put("26215","Airdata"); /*Germany*/ + init.put("26210","Arcor AG & Co"); /*Germany*/ + init.put("26260","DB Telematik"); /*Germany*/ + init.put("262901","Debitel"); /*Germany*/ + init.put("26212","Dolphin Telecom"); /*Germany*/ + init.put("26203","E-Plus"); /*Germany*/ + init.put("26205","E-Plus"); /*Germany*/ + init.put("26277","E-Plus"); /*Germany*/ + init.put("26214","Group 3G UMTS"); /*Germany*/ + init.put("26243","LYCA"); /*Germany*/ + init.put("26213","Mobilcom Multimedia"); /*Germany*/ + init.put("26292","Nash Technologies"); /*Germany*/ + init.put("26207","O2"); /*Germany*/ + init.put("26208","O2"); /*Germany*/ + init.put("26211","O2"); /*Germany*/ + init.put("26276","Siemens AG"); /*Germany*/ + init.put("26201","T-Mobile"); /*Germany*/ + init.put("26206","T-Mobile"); /*Germany*/ + init.put("26216","vistream"); /*Germany*/ + init.put("26202","Vodafone"); /*Germany*/ + init.put("26204","Vodafone"); /*Germany*/ + init.put("26209","Vodafone"); /*Germany*/ + init.put("62006","Airtel"); /*Ghana*/ + init.put("62002","Ghana Telecom Mobile"); /*Ghana*/ + init.put("62004","Kasapa / Hutchison Telecom"); /*Ghana*/ + init.put("62001","MTN"); /*Ghana*/ + init.put("62003","tiGO"); /*Ghana*/ + init.put("26606","CTS Mobile"); /*Gibraltar (United Kingdom)*/ + init.put("26601","GibTel"); /*Gibraltar (United Kingdom)*/ + init.put("20201","Cosmote"); /*Greece*/ + init.put("20205","Vodafone"); /*Greece*/ + init.put("20209","Wind"); /*Greece*/ + init.put("20210","Wind"); /*Greece*/ + init.put("29001","TELE Greenland A/S"); /*Greenland (Denmark)*/ + init.put("352110","Cable & Wireless"); /*Grenada*/ + init.put("352030","Digicel"); /*Grenada*/ + init.put("34020","Digicel"); /*Guadeloupe (France)*/ + init.put("34008","MIO GSM"); /*Guadeloupe (France)*/ + init.put("34001","Orange"); /*Guadeloupe (France)*/ + init.put("34002","Outremer"); /*Guadeloupe (France)*/ + init.put("34003","Telcell"); /*Guadeloupe (France)*/ + init.put("310033","Guam Telephone Authority"); /*Guam (United States)*/ + init.put("310370","Guamcell"); /*Guam (United States)*/ + init.put("310470","Guamcell"); /*Guam (United States)*/ + init.put("311250","i CAN_GSM"); /*Guam (United States)*/ + init.put("310032","IT&E Wireless"); /*Guam (United States)*/ + init.put("310140","mPulse"); /*Guam (United States)*/ + init.put("70401","Claro"); /*Guatemala*/ + init.put("70402","Comcel / Tigo"); /*Guatemala*/ + init.put("70403","movistar"); /*Guatemala*/ + init.put("73801","Digicel"); /*Guiana*/ + init.put("73802","GT&T Cellink Plus"); /*Guiana*/ + init.put("61105","Cellcom"); /*Guinea*/ + init.put("61102","Lagui"); /*Guinea*/ + init.put("61104","MTN"); /*Guinea*/ + init.put("61101","Spacetel"); /*Guinea*/ + init.put("61103","Telecel Guinee"); /*Guinea*/ + init.put("63202","Areeba"); /*Guinea-Bissau*/ + init.put("63203","Orange"); /*Guinea-Bissau*/ + init.put("372010","Comcel / Voila"); /*Haiti*/ + init.put("37202","Digicel"); /*Haiti*/ + init.put("37203","NATCOM"); /*Haiti*/ + init.put("20414","6Gmobile"); /*Holland (Netherlands)*/ + init.put("20423","ASPIDER Solutions Nederland B.V."); /*Holland (Netherlands)*/ + init.put("20427","Breezz Nederland B.V."); /*Holland (Netherlands)*/ + init.put("20425","CapX B.V."); /*Holland (Netherlands)*/ + init.put("20407","eleena (MVNE)"); /*Holland (Netherlands)*/ + init.put("20405","Elephant Talk Communications Premium Rate Services"); /*Holland (Netherlands)*/ + init.put("20417","Intercity Mobile Communications B.V."); /*Holland (Netherlands)*/ + init.put("20408","KPN"); /*Holland (Netherlands)*/ + init.put("20410","KPN"); /*Holland (Netherlands)*/ + init.put("20469","KPN Mobile The Netherlands B.V."); /*Holland (Netherlands)*/ + init.put("20409","Lycamobile"); /*Holland (Netherlands)*/ + init.put("20422","Ministerie van Defensie"); /*Holland (Netherlands)*/ + init.put("20419","Mixe Communication Solutions B.V."); /*Holland (Netherlands)*/ + init.put("20406","Mundio Mobile (Netherlands) Ltd"); /*Holland (Netherlands)*/ + init.put("20421","NS Railinfrabeheer B.V."); /*Holland (Netherlands)*/ + init.put("20420","Orange Nederland"); /*Holland (Netherlands)*/ + init.put("20424","Private Mobility Nederland B.V."); /*Holland (Netherlands)*/ + init.put("20467","RadioAccess B.V."); /*Holland (Netherlands)*/ + init.put("20426","SpeakUp B.V."); /*Holland (Netherlands)*/ + init.put("20416","T-Mobile / Ben"); /*Holland (Netherlands)*/ + init.put("20402","Tele2 Netherlands"); /*Holland (Netherlands)*/ + init.put("20412","Telfort / O2"); /*Holland (Netherlands)*/ + init.put("20413","Unica Installatietechniek B.V"); /*Holland (Netherlands)*/ + init.put("20468","Unify Group Holding B.V."); /*Holland (Netherlands)*/ + init.put("20418","UPC Nederland B.V."); /*Holland (Netherlands)*/ + init.put("20401","VastMobiel B.V."); /*Holland (Netherlands)*/ + init.put("20404","Vodafone"); /*Holland (Netherlands)*/ + init.put("20403","Voiceworks B.V."); /*Holland (Netherlands)*/ + init.put("70802","Celtel / Tigo"); /*Honduras*/ + init.put("70801","Claro"); /*Honduras*/ + init.put("70840","DIGICEL"); /*Honduras*/ + init.put("70830","Hondutel"); /*Honduras*/ + init.put("45403","3 (3G)"); /*Hong Kong (People's Republic of China)*/ + init.put("45405","3 CDMA"); /*Hong Kong (People's Republic of China)*/ + init.put("45404","3 Dual (2G)"); /*Hong Kong (People's Republic of China)*/ + init.put("45412","C Peoples"); /*Hong Kong (People's Republic of China)*/ + init.put("45409","China Motion Telecom"); /*Hong Kong (People's Republic of China)*/ + init.put("45407","China Unicom"); /*Hong Kong (People's Republic of China)*/ + init.put("45411","China-Hongkong Telecom"); /*Hong Kong (People's Republic of China)*/ + init.put("45401","CITIC Telecom 1616"); /*Hong Kong (People's Republic of China)*/ + init.put("45400","CSL"); /*Hong Kong (People's Republic of China)*/ + init.put("45402","CSL 3G"); /*Hong Kong (People's Republic of China)*/ + init.put("45418","Hong Kong CSL Limited"); /*Hong Kong (People's Republic of China)*/ + init.put("45414","Hutchison Telecom"); /*Hong Kong (People's Republic of China)*/ + init.put("45410","New World"); /*Hong Kong (People's Republic of China)*/ + init.put("45416","PCCW"); /*Hong Kong (People's Republic of China)*/ + init.put("45419","PCCW"); /*Hong Kong (People's Republic of China)*/ + init.put("45429","PCCW"); /*Hong Kong (People's Republic of China)*/ + init.put("45415","SmarTone Mobile Comms"); /*Hong Kong (People's Republic of China)*/ + init.put("45417","SmarTone Mobile Comms"); /*Hong Kong (People's Republic of China)*/ + init.put("45406","Smartone-Vodafone"); /*Hong Kong (People's Republic of China)*/ + init.put("45408","Trident"); /*Hong Kong (People's Republic of China)*/ + init.put("21601","Pannon"); /*Hungary*/ + init.put("21630","T-Mobile"); /*Hungary*/ + init.put("21670","Vodafone"); /*Hungary*/ + init.put("27407","IceCell"); /*Iceland*/ + init.put("27411","Nova"); /*Iceland*/ + init.put("27406","N'll nIu ehf"); /*Iceland*/ + init.put("27408","On-waves"); /*Iceland*/ + init.put("27401","Siminn"); /*Iceland*/ + init.put("27412","Tal"); /*Iceland*/ + init.put("27404","Viking"); /*Iceland*/ + init.put("27402","Vodafone"); /*Iceland*/ + init.put("27403","Vodafone"); /*Iceland*/ + init.put("40417","AIRCEL"); /*India*/ + init.put("40425","AIRCEL"); /*India*/ + init.put("40428","AIRCEL"); /*India*/ + init.put("40429","AIRCEL"); /*India*/ + init.put("40437","AIRCEL"); /*India*/ + init.put("40491","AIRCEL"); /*India*/ + init.put("405082","AIRCEL"); /*India*/ + init.put("405800","AIRCEL"); /*India*/ + init.put("405801","AIRCEL"); /*India*/ + init.put("405802","AIRCEL"); /*India*/ + init.put("405803","AIRCEL"); /*India*/ + init.put("405804","AIRCEL"); /*India*/ + init.put("405805","AIRCEL"); /*India*/ + init.put("405806","AIRCEL"); /*India*/ + init.put("405807","AIRCEL"); /*India*/ + init.put("405808","AIRCEL"); /*India*/ + init.put("405809","AIRCEL"); /*India*/ + init.put("405810","AIRCEL"); /*India*/ + init.put("405811","AIRCEL"); /*India*/ + init.put("405812","AIRCEL"); /*India*/ + init.put("405813","AIRCEL"); /*India*/ + init.put("40460","Aircell Digilink"); /*India*/ + init.put("40415","Aircell Digilink Essar Cellph."); /*India*/ + init.put("40406","Airtel"); /*India*/ + init.put("40410","Airtel"); /*India*/ + init.put("40431","Airtel"); /*India*/ + init.put("40440","Airtel"); /*India*/ + init.put("40445","Airtel"); /*India*/ + init.put("40449","Airtel"); /*India*/ + init.put("40470","Airtel"); /*India*/ + init.put("40494","Airtel"); /*India*/ + init.put("40495","Airtel"); /*India*/ + init.put("40497","Airtel"); /*India*/ + init.put("40498","Airtel"); /*India*/ + init.put("40551","Airtel"); /*India*/ + init.put("40552","Airtel"); /*India*/ + init.put("40553","AirTel"); /*India*/ + init.put("40554","AirTel"); /*India*/ + init.put("40555","AirTel"); /*India*/ + init.put("40556","AirTel"); /*India*/ + init.put("40570","AirTel"); /*India*/ + init.put("40496","Airtel - Haryana"); /*India*/ + init.put("40402","Airtel - Punjab"); /*India*/ + init.put("40403","Airtel / Bharti Telenet"); /*India*/ + init.put("40493","Airtel Gujrat"); /*India*/ + init.put("40490","Airtel Maharashtra & Goa"); /*India*/ + init.put("40492","Airtel Mumbai"); /*India*/ + init.put("40443","BPL Mobile Cellular"); /*India*/ + init.put("40421","BPL Mobile Mumbai"); /*India*/ + init.put("40427","BPL USWest Cellular / Cellular Comms"); /*India*/ + init.put("40434","BSNL"); /*India*/ + init.put("40438","BSNL"); /*India*/ + init.put("40451","BSNL"); /*India*/ + init.put("40453","BSNL"); /*India*/ + init.put("40454","BSNL"); /*India*/ + init.put("40455","BSNL"); /*India*/ + init.put("40457","BSNL"); /*India*/ + init.put("40458","BSNL"); /*India*/ + init.put("40459","BSNL"); /*India*/ + init.put("40464","BSNL"); /*India*/ + init.put("40471","BSNL"); /*India*/ + init.put("40473","BSNL"); /*India*/ + init.put("40474","BSNL"); /*India*/ + init.put("40475","BSNL"); /*India*/ + init.put("40476","BSNL"); /*India*/ + init.put("40477","BSNL"); /*India*/ + init.put("40480","BSNL"); /*India*/ + init.put("40481","BSNL"); /*India*/ + init.put("40462","BSNL J&K"); /*India*/ + init.put("40472","BSNL Kerala"); /*India*/ + init.put("40466","BSNL Maharashtra & Goa"); /*India*/ + init.put("40478","BTA Cellcom"); /*India*/ + init.put("40448","Dishnet Wireless"); /*India*/ + init.put("40482","Escorts"); /*India*/ + init.put("40487","Escorts Telecom"); /*India*/ + init.put("40488","Escorts Telecom"); /*India*/ + init.put("40489","Escorts Telecom"); /*India*/ + init.put("40411","Essar / Sterling Cellular"); /*India*/ + init.put("405912","Etisalat DB(cheers)"); /*India*/ + init.put("405913","Etisalat DB(cheers)"); /*India*/ + init.put("405914","Etisalat DB(cheers)"); /*India*/ + init.put("405917","Etisalat DB(cheers)"); /*India*/ + init.put("40566","Hutch"); /*India*/ + init.put("40486","Hutchinson Essar South"); /*India*/ + init.put("40413","Hutchison Essar South"); /*India*/ + init.put("40484","Hutchison Essar South"); /*India*/ + init.put("40419","IDEA"); /*India*/ + init.put("405799","IDEA"); /*India*/ + init.put("405845","IDEA"); /*India*/ + init.put("405848","IDEA"); /*India*/ + init.put("405850","IDEA"); /*India*/ + init.put("40586","IDEA"); /*India*/ + init.put("40412","Idea (Escotel) Haryana"); /*India*/ + init.put("40456","Idea (Escotel) UP West"); /*India*/ + init.put("40404","IDEA CELLULAR - Delhi"); /*India*/ + init.put("40424","IDEA Cellular - Gujarat"); /*India*/ + init.put("40422","IDEA Cellular - Maharashtra"); /*India*/ + init.put("405855","Loop Mobile"); /*India*/ + init.put("405864","Loop Mobile"); /*India*/ + init.put("405865","Loop Mobile"); /*India*/ + init.put("40468","MTNL - Delhi"); /*India*/ + init.put("40469","MTNL - Mumbai"); /*India*/ + init.put("40450","Reliance"); /*India*/ + init.put("40452","Reliance"); /*India*/ + init.put("40467","Reliance"); /*India*/ + init.put("40483","Reliance"); /*India*/ + init.put("40485","Reliance"); /*India*/ + init.put("40501","Reliance"); /*India*/ + init.put("40503","Reliance"); /*India*/ + init.put("40504","Reliance"); /*India*/ + init.put("40509","Reliance"); /*India*/ + init.put("40510","Reliance"); /*India*/ + init.put("40513","Reliance"); /*India*/ + init.put("40409","Reliance Telecom Private"); /*India*/ + init.put("40436","Reliance Telecom Private"); /*India*/ + init.put("40441","RPG MAA"); /*India*/ + init.put("405881","S Tel"); /*India*/ + init.put("40444","Spice Telecom - Karnataka"); /*India*/ + init.put("40414","Spice Telecom - Punjab"); /*India*/ + init.put("40442","Srinivas Cellcom / Aircel"); /*India*/ + init.put("40407","TATA Cellular / Idea Cellular"); /*India*/ + init.put("405025","TATA Teleservice"); /*India*/ + init.put("405026","TATA Teleservice"); /*India*/ + init.put("405027","TATA Teleservice"); /*India*/ + init.put("405029","TATA Teleservice"); /*India*/ + init.put("405030","TATA Teleservice"); /*India*/ + init.put("405031","TATA Teleservice"); /*India*/ + init.put("405032","TATA Teleservice"); /*India*/ + init.put("405033","TATA Teleservice"); /*India*/ + init.put("405034","TATA Teleservice"); /*India*/ + init.put("405035","TATA Teleservice"); /*India*/ + init.put("405036","TATA Teleservice"); /*India*/ + init.put("405037","TATA Teleservice"); /*India*/ + init.put("405038","TATA Teleservice"); /*India*/ + init.put("405039","TATA Teleservice"); /*India*/ + init.put("405040","TATA Teleservice"); /*India*/ + init.put("405041","TATA Teleservice"); /*India*/ + init.put("405042","TATA Teleservice"); /*India*/ + init.put("405043","TATA Teleservice"); /*India*/ + init.put("405044","TATA Teleservice"); /*India*/ + init.put("405045","TATA Teleservice"); /*India*/ + init.put("405046","TATA Teleservice"); /*India*/ + init.put("405047","TATA Teleservice"); /*India*/ + init.put("405818","Uninor"); /*India*/ + init.put("405819","Uninor"); /*India*/ + init.put("405820","Uninor"); /*India*/ + init.put("405821","Uninor"); /*India*/ + init.put("405822","Uninor"); /*India*/ + init.put("405844","Uninor"); /*India*/ + init.put("405875","Uninor"); /*India*/ + init.put("405880","Uninor"); /*India*/ + init.put("405927","Uninor"); /*India*/ + init.put("405929","Uninor"); /*India*/ + init.put("405824","Videocon Datacom"); /*India*/ + init.put("405827","Videocon Datacom"); /*India*/ + init.put("405834","Videocon Datacom"); /*India*/ + init.put("40420","Vodafone"); /*India*/ + init.put("40446","Vodafone"); /*India*/ + init.put("40405","Vodafone - Gujarat"); /*India*/ + init.put("40401","Vodafone - Haryana"); /*India*/ + init.put("40430","Vodafone - Kolkata"); /*India*/ + init.put("405750","Vodafone IN"); /*India*/ + init.put("405751","Vodafone IN"); /*India*/ + init.put("405752","Vodafone IN"); /*India*/ + init.put("405753","Vodafone IN"); /*India*/ + init.put("405754","Vodafone IN"); /*India*/ + init.put("405755","Vodafone IN"); /*India*/ + init.put("405756","Vodafone IN"); /*India*/ + init.put("51089","3"); /*Indonesia*/ + init.put("51008","AXIS"); /*Indonesia*/ + init.put("51027","Ceria"); /*Indonesia*/ + init.put("51099","Esia"); /*Indonesia*/ + init.put("51028","Fren/Hepi"); /*Indonesia*/ + init.put("51021","IM3"); /*Indonesia*/ + init.put("51001","INDOSAT"); /*Indonesia*/ + init.put("51000","PSN"); /*Indonesia*/ + init.put("51009","SMART"); /*Indonesia*/ + init.put("51003","StarOne"); /*Indonesia*/ + init.put("51007","TelkomFlexi"); /*Indonesia*/ + init.put("51020","TELKOMMobile"); /*Indonesia*/ + init.put("51010","Telkomsel"); /*Indonesia*/ + init.put("51011","XL"); /*Indonesia*/ + init.put("43235","Irancell"); /*Iran*/ + init.put("43293","Iraphone"); /*Iran*/ + init.put("43211","MCI"); /*Iran*/ + init.put("43219","MTCE"); /*Iran*/ + init.put("43232","Taliya"); /*Iran*/ + init.put("43270","TCI"); /*Iran*/ + init.put("43214","TKC"); /*Iran*/ + init.put("41805","Asia Cell"); /*Iraq*/ + init.put("41850","Asia Cell"); /*Iraq*/ + init.put("41840","Korek"); /*Iraq*/ + init.put("41845","Mobitel"); /*Iraq*/ + init.put("41892","Omnnea"); /*Iraq*/ + init.put("41808","SanaTel"); /*Iraq*/ + init.put("41820","Zain IQ"); /*Iraq*/ + init.put("41830","Zain IQ"); /*Iraq*/ + init.put("27205","3"); /*Ireland*/ + init.put("27204","Access Telecom"); /*Ireland*/ + init.put("27209","Clever Communications"); /*Ireland*/ + init.put("27200","E-Mobile"); /*Ireland*/ + init.put("27207","Eircom"); /*Ireland*/ + init.put("27211","Liffey Telecom"); /*Ireland*/ + init.put("27203","Meteor"); /*Ireland*/ + init.put("27202","O2"); /*Ireland*/ + init.put("272020","Tesco Mobile"); /*Ireland*/ + init.put("27201","Vodafone"); /*Ireland*/ + init.put("42502","Cellcom"); /*Israel*/ + init.put("42577","Mirs"); /*Israel*/ + init.put("42501","Orange"); /*Israel*/ + init.put("-","Partner"); /*Israel*/ + init.put("42503","Pelephone"); /*Israel*/ + init.put("22299","3 Italia"); /*Italy*/ + init.put("22298","Blu"); /*Italy*/ + init.put("22202","Elsacom"); /*Italy*/ + init.put("22277","IPSE 2000"); /*Italy*/ + init.put("22207","Noverca"); /*Italy*/ + init.put("22230","RFI"); /*Italy*/ + init.put("22201","TIM"); /*Italy*/ + init.put("22210","Vodafone"); /*Italy*/ + init.put("22288","Wind"); /*Italy*/ + init.put("338020","Cable & Wireless"); /*Jamaica*/ + init.put("338180","Cable & Wireless"); /*Jamaica*/ + init.put("338070","Claro"); /*Jamaica*/ + init.put("338050","Digicel"); /*Jamaica*/ + init.put("44001","DoCoMo"); /*Japan*/ + init.put("44002","DoCoMo"); /*Japan*/ + init.put("44003","DoCoMo"); /*Japan*/ + init.put("44009","DoCoMo"); /*Japan*/ + init.put("44010","DoCoMo"); /*Japan*/ + init.put("44011","DoCoMo"); /*Japan*/ + init.put("44012","DoCoMo"); /*Japan*/ + init.put("44013","DoCoMo"); /*Japan*/ + init.put("44014","DoCoMo"); /*Japan*/ + init.put("44015","DoCoMo"); /*Japan*/ + init.put("44016","DoCoMo"); /*Japan*/ + init.put("44017","DoCoMo"); /*Japan*/ + init.put("44018","DoCoMo"); /*Japan*/ + init.put("44019","DoCoMo"); /*Japan*/ + init.put("44021","DoCoMo"); /*Japan*/ + init.put("44022","DoCoMo"); /*Japan*/ + init.put("44023","DoCoMo"); /*Japan*/ + init.put("44024","DoCoMo"); /*Japan*/ + init.put("44025","DoCoMo"); /*Japan*/ + init.put("44026","DoCoMo"); /*Japan*/ + init.put("44027","DoCoMo"); /*Japan*/ + init.put("44028","DoCoMo"); /*Japan*/ + init.put("44029","DoCoMo"); /*Japan*/ + init.put("44030","DoCoMo"); /*Japan*/ + init.put("44031","DoCoMo"); /*Japan*/ + init.put("44032","DoCoMo"); /*Japan*/ + init.put("44033","DoCoMo"); /*Japan*/ + init.put("44034","DoCoMo"); /*Japan*/ + init.put("44035","DoCoMo"); /*Japan*/ + init.put("44036","DoCoMo"); /*Japan*/ + init.put("44037","DoCoMo"); /*Japan*/ + init.put("44038","DoCoMo"); /*Japan*/ + init.put("44039","DoCoMo"); /*Japan*/ + init.put("44049","DoCoMo"); /*Japan*/ + init.put("44058","DoCoMo"); /*Japan*/ + init.put("44060","DoCoMo"); /*Japan*/ + init.put("44061","DoCoMo"); /*Japan*/ + init.put("44062","DoCoMo"); /*Japan*/ + init.put("44063","DoCoMo"); /*Japan*/ + init.put("44064","DoCoMo"); /*Japan*/ + init.put("44065","DoCoMo"); /*Japan*/ + init.put("44066","DoCoMo"); /*Japan*/ + init.put("44067","DoCoMo"); /*Japan*/ + init.put("44068","DoCoMo"); /*Japan*/ + init.put("44069","DoCoMo"); /*Japan*/ + init.put("44087","DoCoMo"); /*Japan*/ + init.put("44099","DoCoMo"); /*Japan*/ + init.put("44000","eMobile"); /*Japan*/ + init.put("44007","KDDI"); /*Japan*/ + init.put("44008","KDDI"); /*Japan*/ + init.put("44050","KDDI"); /*Japan*/ + init.put("44051","KDDI"); /*Japan*/ + init.put("44052","KDDI"); /*Japan*/ + init.put("44053","KDDI"); /*Japan*/ + init.put("44054","KDDI"); /*Japan*/ + init.put("44055","KDDI"); /*Japan*/ + init.put("44056","KDDI"); /*Japan*/ + init.put("44070","KDDI"); /*Japan*/ + init.put("44071","KDDI"); /*Japan*/ + init.put("44072","KDDI"); /*Japan*/ + init.put("44073","KDDI"); /*Japan*/ + init.put("44074","KDDI"); /*Japan*/ + init.put("44075","KDDI"); /*Japan*/ + init.put("44076","KDDI"); /*Japan*/ + init.put("44077","KDDI"); /*Japan*/ + init.put("44079","KDDI"); /*Japan*/ + init.put("44088","KDDI"); /*Japan*/ + init.put("44089","KDDI"); /*Japan*/ + init.put("44078","Okinawa Cellular Telephone"); /*Japan*/ + init.put("44020","SoftBank"); /*Japan*/ + init.put("44080","TU-KA"); /*Japan*/ + init.put("44081","TU-KA"); /*Japan*/ + init.put("44082","TU-KA"); /*Japan*/ + init.put("44083","TU-KA"); /*Japan*/ + init.put("44084","TU-KA"); /*Japan*/ + init.put("44085","TU-KA"); /*Japan*/ + init.put("44086","TU-KA"); /*Japan*/ + init.put("44004","Vodafone"); /*Japan*/ + init.put("44006","Vodafone"); /*Japan*/ + init.put("44040","Vodafone"); /*Japan*/ + init.put("44041","Vodafone"); /*Japan*/ + init.put("44042","Vodafone"); /*Japan*/ + init.put("44043","Vodafone"); /*Japan*/ + init.put("44044","Vodafone"); /*Japan*/ + init.put("44045","Vodafone"); /*Japan*/ + init.put("44046","Vodafone"); /*Japan*/ + init.put("44047","Vodafone"); /*Japan*/ + init.put("44048","Vodafone"); /*Japan*/ + init.put("44090","Vodafone"); /*Japan*/ + init.put("44092","Vodafone"); /*Japan*/ + init.put("44093","Vodafone"); /*Japan*/ + init.put("44094","Vodafone"); /*Japan*/ + init.put("44095","Vodafone"); /*Japan*/ + init.put("44096","Vodafone"); /*Japan*/ + init.put("44097","Vodafone"); /*Japan*/ + init.put("44098","Vodafone"); /*Japan*/ + init.put("41677","Orange"); /*Jordan*/ + init.put("41603","Umniah"); /*Jordan*/ + init.put("41602","XPress Telecom"); /*Jordan*/ + init.put("41601","Zain"); /*Jordan*/ + init.put("40101","Beeline"); /*Kazakhstan*/ + init.put("40107","Dalacom"); /*Kazakhstan*/ + init.put("40102","K'Cell"); /*Kazakhstan*/ + init.put("40108","Kazakhtelecom"); /*Kazakhstan*/ + init.put("40177","Mobile Telecom Service"); /*Kazakhstan*/ + init.put("63907","Orange Kenya"); /*Kenya*/ + init.put("63902","Safaricom"); /*Kenya*/ + init.put("63905","yu"); /*Kenya*/ + init.put("63903","Zain"); /*Kenya*/ + init.put("54509","Kiribati Frigate"); /*Kiribati*/ + init.put("41904","Viva"); /*Kuwait*/ + init.put("41903","Wataniya"); /*Kuwait*/ + init.put("41902","Zain"); /*Kuwait*/ + init.put("43701","Bitel"); /*Kyrgyzstan*/ + init.put("43703","Fonex"); /*Kyrgyzstan*/ + init.put("43705","MegaCom"); /*Kyrgyzstan*/ + init.put("43709","O!"); /*Kyrgyzstan*/ + init.put("45702","ETL"); /*Laos*/ + init.put("45701","LaoTel"); /*Laos*/ + init.put("45703","LAT"); /*Laos*/ + init.put("45708","Tigo"); /*Laos*/ + init.put("24705","Bite"); /*Latvia*/ + init.put("24709","Camel Mobile"); /*Latvia*/ + init.put("24708","IZZI"); /*Latvia*/ + init.put("24701","LMT"); /*Latvia*/ + init.put("24707","MTS"); /*Latvia*/ + init.put("24706","Rigatta"); /*Latvia*/ + init.put("24702","Tele2"); /*Latvia*/ + init.put("24703","TRIATEL"); /*Latvia*/ + init.put("41501","Alfa"); /*Lebanon*/ + init.put("41503","MTC-Touch"); /*Lebanon*/ + init.put("41505","Ogero Mobile"); /*Lebanon*/ + init.put("65102","Econet Ezin-cel"); /*Lesotho*/ + init.put("65101","Vodacom"); /*Lesotho*/ + init.put("60602","Al-Jeel Phone"); /*Libya*/ + init.put("60606","Hatef Libya"); /*Libya*/ + init.put("60603","Libya Phone"); /*Libya*/ + init.put("60600","Libyana"); /*Libya*/ + init.put("60601","Madar"); /*Libya*/ + init.put("29504","Cubic Telecom"); /*Liechtenstein*/ + init.put("29505","FL1"); /*Liechtenstein*/ + init.put("29502","Orange"); /*Liechtenstein*/ + init.put("29501","Swisscom"); /*Liechtenstein*/ + init.put("29577","Tele 2"); /*Liechtenstein*/ + init.put("24602","BITE"); /*Lithuania*/ + init.put("24605","LitRail"); /*Lithuania*/ + init.put("24606","Mediafon"); /*Lithuania*/ + init.put("24601","Omnitel"); /*Lithuania*/ + init.put("24603","Tele 2"); /*Lithuania*/ + init.put("61807","Cellcom"); /*Livery*/ + init.put("61804","Comium Liberi"); /*Livery*/ + init.put("61802","Libercell"); /*Livery*/ + init.put("61820","LIBTELCO"); /*Livery*/ + init.put("61801","Lonestar Cell"); /*Livery*/ + init.put("27001","LuxGSM"); /*Luksemburg*/ + init.put("27077","Tango"); /*Luksemburg*/ + init.put("27099","Voxmobile"); /*Luksemburg*/ + init.put("45503","3"); /*Macao (People's Republic of China)*/ + init.put("45505","3"); /*Macao (People's Republic of China)*/ + init.put("45502","China Telecom"); /*Macao (People's Republic of China)*/ + init.put("45501","CTM"); /*Macao (People's Republic of China)*/ + init.put("45504","CTM"); /*Macao (People's Republic of China)*/ + init.put("45500","SmarTone"); /*Macao (People's Republic of China)*/ + init.put("64602","Orange"); /*Madagascar*/ + init.put("64603","Sacel"); /*Madagascar*/ + init.put("64604","Telma"); /*Madagascar*/ + init.put("64601","Zain"); /*Madagascar*/ + init.put("65001","TNM"); /*Malawi*/ + init.put("65010","Zain"); /*Malawi*/ + init.put("50201","ATUR 450"); /*Malaysia*/ + init.put("502151","Baraka Telecom Sdn Bhd (MVNE)"); /*Malaysia*/ + init.put("50213","Celcom"); /*Malaysia*/ + init.put("50219","Celcom"); /*Malaysia*/ + init.put("50216","DiGi"); /*Malaysia*/ + init.put("50210","DiGi Telecommunications"); /*Malaysia*/ + init.put("50220","Electcoms Wireless Sdn Bhd"); /*Malaysia*/ + init.put("50212","Maxis"); /*Malaysia*/ + init.put("50217","Maxis"); /*Malaysia*/ + init.put("50214","Telekom Malaysia Berhad for PSTN SMS"); /*Malaysia*/ + init.put("50211","TM Homeline"); /*Malaysia*/ + init.put("502150","Tune Talk Sdn Bhd"); /*Malaysia*/ + init.put("50218","U Mobile"); /*Malaysia*/ + init.put("502152","Yes"); /*Malaysia*/ + init.put("47201","Dhiraagu"); /*Maldives*/ + init.put("47202","Wataniya"); /*Maldives*/ + init.put("61001","Malitel"); /*Mali*/ + init.put("61002","Orange"); /*Mali*/ + init.put("27821","GO"); /*Malta*/ + init.put("27877","Melita"); /*Malta*/ + init.put("27801","Vodafone"); /*Malta*/ + init.put("60902","Chinguitel"); /*Mauretania*/ + init.put("60901","Mattel"); /*Mauretania*/ + init.put("60910","Mauritel"); /*Mauretania*/ + init.put("61710","Emtel"); /*Mauritius*/ + init.put("61702","Mahanagar Telephone (Mauritius) Ltd."); /*Mauritius*/ + init.put("61701","Orange"); /*Mauritius*/ + init.put("334050","Iusacell"); /*Mexico*/ + init.put("33403","movistar"); /*Mexico*/ + init.put("334030","movistar"); /*Mexico*/ + init.put("33401","Nextel"); /*Mexico*/ + init.put("334010","Nextel"); /*Mexico*/ + init.put("33402","Telcel"); /*Mexico*/ + init.put("334020","Telcel"); /*Mexico*/ + init.put("55001","FSM Telecom"); /*Micronesia*/ + init.put("25904","Eventis"); /*Moldova*/ + init.put("25903","IDC"); /*Moldova*/ + init.put("25902","Moldcell"); /*Moldova*/ + init.put("25901","Orange"); /*Moldova*/ + init.put("25905","UnitE"); /*Moldova*/ + init.put("25999","UnitE"); /*Moldova*/ + init.put("21201","Office des Telephones"); /*Monaco*/ + init.put("42898","G.Mobile"); /*Mongolia*/ + init.put("42899","MobiCom"); /*Mongolia*/ + init.put("42891","Skytel"); /*Mongolia*/ + init.put("42888","Unitel"); /*Mongolia*/ + init.put("29703","m:tel CG"); /*Montenegro*/ + init.put("22004","T-Mobile"); /*Montenegro*/ + init.put("29702","T-Mobile"); /*Montenegro*/ + init.put("29704","T-Mobile"); /*Montenegro*/ + init.put("29701","Telenor Montenegro"); /*Montenegro*/ + init.put("60401","IAM"); /*Morocco*/ + init.put("60405","INWI"); /*Morocco*/ + init.put("60400","Meditel"); /*Morocco*/ + init.put("64301","mCel"); /*Mozambique*/ + init.put("64304","Vodacom"); /*Mozambique*/ + init.put("41401","MPT"); /*Myanmar*/ + init.put("64903","Cell One"); /*Namibia*/ + init.put("64901","MTC"); /*Namibia*/ + init.put("64902","switch"); /*Namibia*/ + init.put("53602","Digicel"); /*Nauru*/ + init.put("42902","Mero Mobile"); /*Nepal*/ + init.put("42901","Nepal Telecom"); /*Nepal*/ + init.put("42904","SmartCell"); /*Nepal*/ + init.put("42903","United Telecom Limited"); /*Nepal*/ + init.put("36294","Bayus"); /*Netherlands Antilles (Netherlands)*/ + init.put("36269","Digicel"); /*Netherlands Antilles (Netherlands)*/ + init.put("36295","MIO"); /*Netherlands Antilles (Netherlands)*/ + init.put("36251","Telcell"); /*Netherlands Antilles (Netherlands)*/ + init.put("36291","UTS"); /*Netherlands Antilles (Netherlands)*/ + init.put("54601","Mobilis"); /*New Caledonia (France)*/ + init.put("53024","NZ Comms"); /*New Zealand*/ + init.put("53000","Telecom"); /*New Zealand*/ + init.put("53002","Telecom"); /*New Zealand*/ + init.put("53005","Telecom"); /*New Zealand*/ + init.put("53004","TelstraClear"); /*New Zealand*/ + init.put("53001","Vodafone"); /*New Zealand*/ + init.put("53003","Woosh"); /*New Zealand*/ + init.put("71021","Claro"); /*Nicaragua*/ + init.put("71030","movistar"); /*Nicaragua*/ + init.put("71073","SERCOM"); /*Nicaragua*/ + init.put("61404","Orange"); /*Niger*/ + init.put("61401","SahelCom"); /*Niger*/ + init.put("61403","Telecel"); /*Niger*/ + init.put("61402","Zain"); /*Niger*/ + init.put("62160","Etisalat"); /*Nigeria*/ + init.put("62150","Glo"); /*Nigeria*/ + init.put("62140","M-Tel"); /*Nigeria*/ + init.put("62130","MTN"); /*Nigeria*/ + init.put("62125","Visafone"); /*Nigeria*/ + init.put("62120","Zain"); /*Nigeria*/ + init.put("55501","Telecom Niue"); /*Niue*/ + init.put("467192","Koryolink"); /*North Korea*/ + init.put("467193","SUN NET"); /*North Korea*/ + init.put("24209","Barablu Mobile Norway Ltd"); /*Norway*/ + init.put("24206","Ice"); /*Norway*/ + init.put("24220","Jernbaneverket AS"); /*Norway*/ + init.put("24223","Lyca"); /*Norway*/ + init.put("24203","MTU"); /*Norway*/ + init.put("24202","NetCom"); /*Norway*/ + init.put("24205","Network Norway"); /*Norway*/ + init.put("24211","SystemNet"); /*Norway*/ + init.put("24208","TDC Mobil AS"); /*Norway*/ + init.put("24204","Tele2"); /*Norway*/ + init.put("24201","Telenor"); /*Norway*/ + init.put("--","Telia"); /*Norway*/ + init.put("24207","Ventelo"); /*Norway*/ + init.put("42203","Nawras"); /*Oman*/ + init.put("42202","Oman Mobile"); /*Oman*/ + init.put("25030","Megafon"); /*Osetia*/ + init.put("41008","Instaphone"); /*Pakistan*/ + init.put("41001","Mobilink"); /*Pakistan*/ + init.put("41006","Telenor"); /*Pakistan*/ + init.put("41003","Ufone"); /*Pakistan*/ + init.put("41007","Warid"); /*Pakistan*/ + init.put("41004","Zong"); /*Pakistan*/ + init.put("55280","Palau Mobile"); /*Palau*/ + init.put("55201","PNCC"); /*Palau*/ + init.put("42505","JAWWAL"); /*Palestine*/ + init.put("42506","Wataniya"); /*Palestine*/ + init.put("71401","Cable & Wireless"); /*Panama*/ + init.put("71404","Digicel"); /*Panama*/ + init.put("71403","laro"); /*Panama*/ + init.put("71402","movistar"); /*Panama*/ + init.put("53701","B-Mobile"); /*Papua New Guinea*/ + init.put("53703","Digicel"); /*Papua New Guinea*/ + init.put("74402","Claro"); /*Paraguay*/ + init.put("74406","Copaco"); /*Paraguay*/ + init.put("74405","Personal"); /*Paraguay*/ + init.put("74404","Tigo"); /*Paraguay*/ + init.put("74401","VOX"); /*Paraguay*/ + init.put("71610","Claro"); /*Peru*/ + init.put("71606","movistar"); /*Peru*/ + init.put("71607","NEXTEL"); /*Peru*/ + init.put("51511","ACeS Philippines"); /*Philippines*/ + init.put("51505","Digitel"); /*Philippines*/ + init.put("51502","Globe"); /*Philippines*/ + init.put("51501","Islacom"); /*Philippines*/ + init.put("51588","Nextel"); /*Philippines*/ + init.put("51518","Red Mobile"); /*Philippines*/ + init.put("51503","Smart Gold"); /*Philippines*/ + init.put("26017","Aero2"); /*Poland*/ + init.put("26015","CenterNet"); /*Poland*/ + init.put("26012","Cyfrowy Polsat"); /*Poland*/ + init.put("26008","E-Telko"); /*Poland*/ + init.put("26016","Mobyland"); /*Poland*/ + init.put("26011","Nordisk Polska"); /*Poland*/ + init.put("26003","Orange"); /*Poland*/ + init.put("26006","Play"); /*Poland*/ + init.put("26001","Plus"); /*Poland*/ + init.put("26005","Polska Telefonia"); /*Poland*/ + init.put("26007","Premium Internet"); /*Poland*/ + init.put("26013","Sferia"); /*Poland*/ + init.put("26002","T-mobile"); /*Poland*/ + init.put("26004","Tele2"); /*Poland*/ + init.put("26010","Telefony Opalenickie"); /*Poland*/ + init.put("26009","Telekomunikacja Kolejowa"); /*Poland*/ + init.put("26803","Optimus"); /*Portugal*/ + init.put("26806","TMN"); /*Portugal*/ + init.put("26801","Vodafone"); /*Portugal*/ + init.put("26821","Zapp"); /*Portugal*/ + init.put("33011","Claro"); /*Puerto Rico*/ + init.put("330110","Claro"); /*Puerto Rico*/ + init.put("33000","Open Mobile"); /*Puerto Rico*/ + init.put("42705","Ministry of Interior"); /*Qatar*/ + init.put("42701","Qatarnet"); /*Qatar*/ + init.put("42702","Vodafone"); /*Qatar*/ + init.put("62910","Libertis Telecom"); /*Republic of Congo*/ + init.put("62907","Warid Telecom"); /*Republic of Congo*/ + init.put("62901","Zain"); /*Republic of Congo*/ + init.put("29402","Cosmofon"); /*Republic of Macedonia*/ + init.put("29401","T-Mobile"); /*Republic of Macedonia*/ + init.put("29403","VIP"); /*Republic of Macedonia*/ + init.put("64700","Orange"); /*Reunion (France)*/ + init.put("64702","Outremer"); /*Reunion (France)*/ + init.put("64710","SFR Reunion"); /*Reunion (France)*/ + init.put("22603","Cosmote"); /*Romania*/ + init.put("22605","DIGI.mobil"); /*Romania*/ + init.put("22611","Enigma-System"); /*Romania*/ + init.put("22610","Orange"); /*Romania*/ + init.put("22602","Romtelecom"); /*Romania*/ + init.put("22601","Vodafone"); /*Romania*/ + init.put("22604","Zapp"); /*Romania*/ + init.put("22606","Zapp"); /*Romania*/ + init.put("25012","Baykalwestcom"); /*Russian Federation*/ + init.put("25028","Beeline"); /*Russian Federation*/ + init.put("25099","Beeline"); /*Russian Federation*/ + init.put("25010","DTC"); /*Russian Federation*/ + init.put("25005","ETK"); /*Russian Federation*/ + init.put("25019","INDIGO"); /*Russian Federation*/ + init.put("25013","KUGSM"); /*Russian Federation*/ + init.put("25002","MegaFon"); /*Russian Federation*/ + init.put("25023","Mobicom - Novosibirsk"); /*Russian Federation*/ + init.put("25035","MOTIV"); /*Russian Federation*/ + init.put("25001","MTS"); /*Russian Federation*/ + init.put("25003","NCC"); /*Russian Federation*/ + init.put("25016","NTC"); /*Russian Federation*/ + init.put("25011","Orensot"); /*Russian Federation*/ + init.put("25092","Primtelefon"); /*Russian Federation*/ + init.put("25004","Sibchallenge"); /*Russian Federation*/ + init.put("25006","Skylink"); /*Russian Federation*/ + init.put("25009","Skylink"); /*Russian Federation*/ + init.put("25007","SMARTS"); /*Russian Federation*/ + init.put("25014","SMARTS"); /*Russian Federation*/ + init.put("25015","SMARTS"); /*Russian Federation*/ + init.put("25044","Stavtelesot / North Caucasian GSM"); /*Russian Federation*/ + init.put("25038","Tambov GSM"); /*Russian Federation*/ + init.put("25020","Tele2"); /*Russian Federation*/ + init.put("25093","Telecom XXI"); /*Russian Federation*/ + init.put("25017","Utel"); /*Russian Federation*/ + init.put("25039","Utel"); /*Russian Federation*/ + init.put("63510","MTN"); /*Rwanda*/ + init.put("63512","Rwandatel"); /*Rwanda*/ + init.put("63513","Tigo"); /*Rwanda*/ + init.put("356110","Cable & Wireless"); /*Saint Kitts and Nevis*/ + init.put("356070","Chippie"); /*Saint Kitts and Nevis*/ + init.put("356050","Digicel"); /*Saint Kitts and Nevis*/ + init.put("358110","Cable & Wireless"); /*Saint Lucia*/ + init.put("358050","Digicel"); /*Saint Lucia*/ + init.put("360110","Cable & Wireless"); /*Saint Vincent and the Grenadines*/ + init.put("360100","Cingular Wireless"); /*Saint Vincent and the Grenadines*/ + init.put("360050","Digicel"); /*Saint Vincent and the Grenadines*/ + init.put("360070","Digicel"); /*Saint Vincent and the Grenadines*/ + init.put("30801","Ameris"); /*Saint-Pierre and Miquelon (France)*/ + init.put("54901","Digicel"); /*Samoa*/ + init.put("54927","SamoaTel"); /*Samoa*/ + init.put("29201","PRIMA"); /*San Marino*/ + init.put("62601","CSTmovel"); /*Sao Tome and Principe*/ + init.put("42007","EAE"); /*Saudi Arabia*/ + init.put("42003","Mobily"); /*Saudi Arabia*/ + init.put("42001","STC"); /*Saudi Arabia*/ + init.put("42004","Zain SA"); /*Saudi Arabia*/ + init.put("60803","Expresso"); /*Senegal*/ + init.put("60802","Sentel GSM"); /*Senegal*/ + init.put("60801","Sonatel ALIZE"); /*Senegal*/ + init.put("22003","Telekom Srbija"); /*Serbia*/ + init.put("22001","Telenor"); /*Serbia*/ + init.put("22005","VIP Mobile"); /*Serbia*/ + init.put("63301","Cable & Wireless (Seychelles) Ltd."); /*Seychelles*/ + init.put("63302","Mediatech International"); /*Seychelles*/ + init.put("63310","Telecom Airtel"); /*Seychelles*/ + init.put("61905","Africell"); /*Sierra Leone*/ + init.put("61904","Comium"); /*Sierra Leone*/ + init.put("61903","Datatel"); /*Sierra Leone*/ + init.put("61902","Millicom"); /*Sierra Leone*/ + init.put("61925","Mobitel"); /*Sierra Leone*/ + init.put("61901","Zain"); /*Sierra Leone*/ + init.put("52512","Digital Trunked Radio Network"); /*Singapore*/ + init.put("52503","M1"); /*Singapore*/ + init.put("52501","SingTel"); /*Singapore*/ + init.put("52502","SingTel-G18"); /*Singapore*/ + init.put("52505","StarHub"); /*Singapore*/ + init.put("23105","Mobile Entertainment Company"); /*Slovakia*/ + init.put("23106","O2"); /*Slovakia*/ + init.put("23101","Orange"); /*Slovakia*/ + init.put("23102","T-Mobile"); /*Slovakia*/ + init.put("23104","T-Mobile"); /*Slovakia*/ + init.put("23103","Unient Communications"); /*Slovakia*/ + init.put("23199","eSR"); /*Slovakia*/ + init.put("29341","Mobitel"); /*Slovenia*/ + init.put("29340","SI.mobil - Vodafone"); /*Slovenia*/ + init.put("29364","T-2"); /*Slovenia*/ + init.put("29370","Tusmobil"); /*Slovenia*/ + init.put("54001","BREEZE"); /*Solomon Islands*/ + init.put("5401","BREEZE"); /*Solomon Islands*/ + init.put("63730","Golis"); /*Somalia*/ + init.put("63725","Hormuud"); /*Somalia*/ + init.put("63710","Nationlink"); /*Somalia*/ + init.put("63760","Nationlink Telecom"); /*Somalia*/ + init.put("63704","Somafone"); /*Somalia*/ + init.put("638","Telcom Mobile"); /*Somalia*/ + init.put("63701","Telesom"); /*Somalia*/ + init.put("63782","Telesom"); /*Somalia*/ + init.put("65530","Bokamoso Consortium"); /*South Africa*/ + init.put("65521","Cape Town Metropolitan Council"); /*South Africa*/ + init.put("65507","Cell C"); /*South Africa*/ + init.put("65532","Ilizwi Telecommunications"); /*South Africa*/ + init.put("65531","Karabo Telecoms (Pty) Ltd."); /*South Africa*/ + init.put("65510","MTN"); /*South Africa*/ + init.put("65513","Neotel"); /*South Africa*/ + init.put("65511","SAPS Gauteng"); /*South Africa*/ + init.put("65506","Sentech"); /*South Africa*/ + init.put("65502","Telkom Mobile / 8.ta"); /*South Africa*/ + init.put("65533","Thinta Thinta Telecommunications"); /*South Africa*/ + init.put("65501","Vodacom"); /*South Africa*/ + init.put("45004","KT"); /*South Korea*/ + init.put("45008","KTF"); /*South Korea*/ + init.put("45002","KTF CDMA"); /*South Korea*/ + init.put("45006","LGU+"); /*South Korea*/ + init.put("45003","Power 017"); /*South Korea*/ + init.put("45005","SK Telecom"); /*South Korea*/ + init.put("21423","BARABLU"); /*Spain*/ + init.put("21415","BT"); /*Spain*/ + init.put("21422","DigiMobil"); /*Spain*/ + init.put("21424","Eroski"); /*Spain*/ + init.put("21408","Euskaltel"); /*Spain*/ + init.put("21420","Fonyou"); /*Spain*/ + init.put("21425","LycaMobile"); /*Spain*/ + init.put("21407","movistar"); /*Spain*/ + init.put("21417","MUbil R"); /*Spain*/ + init.put("21418","ONO"); /*Spain*/ + init.put("21403","Orange"); /*Spain*/ + init.put("21409","Orange"); /*Spain*/ + init.put("21419","Simyo"); /*Spain*/ + init.put("21416","TeleCable"); /*Spain*/ + init.put("21405","TME"); /*Spain*/ + init.put("21401","Vodafone"); /*Spain*/ + init.put("21406","Vodafone"); /*Spain*/ + init.put("21404","Yoigo"); /*Spain*/ + init.put("41305","Airtel"); /*Sri Lanka*/ + init.put("41302","Dialog"); /*Sri Lanka*/ + init.put("41308","Hutch Sri Lanka"); /*Sri Lanka*/ + init.put("41301","Mobitel"); /*Sri Lanka*/ + init.put("41303","Tigo"); /*Sri Lanka*/ + init.put("63401","Mobitel / Mobile Telephone Company"); /*Sudan*/ + init.put("63402","MTN"); /*Sudan*/ + init.put("63407","Sudani One"); /*Sudan*/ + init.put("63405","Vivacell"); /*Sudan*/ + init.put("74603","Digicel"); /*Suriname*/ + init.put("74602","Telesu"); /*Suriname*/ + init.put("74604","Uniqa"); /*Suriname*/ + init.put("65310","Swazi MTN"); /*Swaziland*/ + init.put("24002","3 HUTCHISON"); /*Sweden*/ + init.put("24004","3G Infrastructure Services"); /*Sweden*/ + init.put("24016","42IT"); /*Sweden*/ + init.put("24021","Banverket"); /*Sweden*/ + init.put("24012","Barablu Mobile Scandinavia"); /*Sweden*/ + init.put("24026","Beepsend"); /*Sweden*/ + init.put("24025","DigiTelMobile"); /*Sweden*/ + init.put("24017","Gotanet"); /*Sweden*/ + init.put("24000","Halebop"); /*Sweden*/ + init.put("24011","Lindholmen Science Park"); /*Sweden*/ + init.put("24033","Mobile Arts AB"); /*Sweden*/ + init.put("24003","Nordisk Mobiltelefon"); /*Sweden*/ + init.put("24010","SpringMobil"); /*Sweden*/ + init.put("24024","Sweden 2G"); /*Sweden*/ + init.put("24024","Sweden 2G"); /*Sweden*/ + init.put("24005","Sweden 3G"); /*Sweden*/ + init.put("24014","TDC Mobil"); /*Sweden*/ + init.put("24007","Tele2Comviq"); /*Sweden*/ + init.put("24006","Telenor"); /*Sweden*/ + init.put("24008","Telenor"); /*Sweden*/ + init.put("24009","Telenor Mobile Sverige"); /*Sweden*/ + init.put("24001","TeliaSonera Mobile Networks"); /*Sweden*/ + init.put("24013","Ventelo Sverige"); /*Sweden*/ + init.put("24020","Wireless Maingate"); /*Sweden*/ + init.put("24015","Wireless Maingate Nordic"); /*Sweden*/ + init.put("22850","3G Mobile AG"); /*Switzerland*/ + init.put("22851","BebbiCell AG"); /*Switzerland*/ + init.put("22807","IN&Phone"); /*Switzerland*/ + init.put("22803","Orange"); /*Switzerland*/ + init.put("22806","SBB AG"); /*Switzerland*/ + init.put("22802","Sunrise"); /*Switzerland*/ + init.put("22801","Swisscom"); /*Switzerland*/ + init.put("22808","Tele2"); /*Switzerland*/ + init.put("22805","Togewanet AG (Comfone)"); /*Switzerland*/ + init.put("41702","MTN Syria"); /*Syria*/ + init.put("41701","SyriaTel"); /*Syria*/ + init.put("46602","APTG"); /*Taiwan*/ + init.put("46605","APTG"); /*Taiwan*/ + init.put("46611","Chunghwa LDM"); /*Taiwan*/ + init.put("46692","Chungwa"); /*Taiwan*/ + init.put("46601","FarEasTone"); /*Taiwan*/ + init.put("46688","KG Telecom"); /*Taiwan*/ + init.put("46693","MobiTai"); /*Taiwan*/ + init.put("46697","Taiwan Mobile"); /*Taiwan*/ + init.put("46699","TransAsia"); /*Taiwan*/ + init.put("46606","Tuntex"); /*Taiwan*/ + init.put("46689","VIBO"); /*Taiwan*/ + init.put("43604","Babilon-M"); /*Tajikistan*/ + init.put("43605","CTJTHSC Tajik-tel"); /*Tajikistan*/ + init.put("43602","Indigo"); /*Tajikistan*/ + init.put("43603","MLT"); /*Tajikistan*/ + init.put("43601","Somoncom"); /*Tajikistan*/ + init.put("43612","Tcell"); /*Tajikistan*/ + init.put("64009","Hits"); /*Tanzania*/ + init.put("64002","Mobitel"); /*Tanzania*/ + init.put("64006","Sasatel"); /*Tanzania*/ + init.put("64011","SmileCom"); /*Tanzania*/ + init.put("64001","Tritel"); /*Tanzania*/ + init.put("64007","TTCL Mobile"); /*Tanzania*/ + init.put("64008","TTCL Mobile"); /*Tanzania*/ + init.put("64004","Vodacom"); /*Tanzania*/ + init.put("64005","Zain"); /*Tanzania*/ + init.put("64003","Zantel"); /*Tanzania*/ + init.put("52015","ACT Mobile"); /*Thailand*/ + init.put("52001","Advanced Info Service"); /*Thailand*/ + init.put("52023","Advanced Info Service"); /*Thailand*/ + init.put("52000","CAT CDMA"); /*Thailand*/ + init.put("52002","CAT CDMA"); /*Thailand*/ + init.put("52018","DTAC"); /*Thailand*/ + init.put("52099","True Move"); /*Thailand*/ + init.put("52010","WCS IQ"); /*Thailand*/ + init.put("61503","Moov"); /*Togo*/ + init.put("61505","Telecel"); /*Togo*/ + init.put("61501","Togo Cell"); /*Togo*/ + init.put("53988","Digicel"); /*Tonga*/ + init.put("53943","Shoreline Communication"); /*Tonga*/ + init.put("53901","Tonga Communications Corporation"); /*Tonga*/ + init.put("37412","bmobile"); /*Trinidad and Tobago*/ + init.put("37413","Digicel"); /*Trinidad and Tobago*/ + init.put("374130","Digicel"); /*Trinidad and Tobago*/ + init.put("60501","Orange"); /*Tunisia*/ + init.put("60502","Tunicell"); /*Tunisia*/ + init.put("60503","Tunisiana"); /*Tunisia*/ + init.put("28603","Avea"); /*Turkey*/ + init.put("28604","Aycell"); /*Turkey*/ + init.put("28601","Turkcell"); /*Turkey*/ + init.put("28602","Vodafone"); /*Turkey*/ + init.put("43801","MTS"); /*Turkmenistan*/ + init.put("43802","TM-Cell"); /*Turkmenistan*/ + init.put("55301","TTC"); /*Tuvalu*/ + init.put("64110","MTN"); /*Uganda*/ + init.put("64114","Orange"); /*Uganda*/ + init.put("64111","Uganda Telecom Ltd."); /*Uganda*/ + init.put("64122","Warid Telecom"); /*Uganda*/ + init.put("64101","Zain"); /*Uganda*/ + init.put("25502","Beeline"); /*Ukraine*/ + init.put("25523","CDMA Ukraine"); /*Ukraine*/ + init.put("25505","Golden Telecom"); /*Ukraine*/ + init.put("25504","IT"); /*Ukraine*/ + init.put("25503","Kyivstar"); /*Ukraine*/ + init.put("25506","life:)"); /*Ukraine*/ + init.put("25501","MTS"); /*Ukraine*/ + init.put("25521","PEOPLEnet"); /*Ukraine*/ + init.put("25507","Utel"); /*Ukraine*/ + init.put("42403","du"); /*United Arab Emirates*/ + init.put("42402","Etisalat"); /*United Arab Emirates*/ + init.put("23420","3 Hutchison"); /*United Kingdom*/ + init.put("23400","BT"); /*United Kingdom*/ + init.put("23455","Cable & Wireless / Sure Mobile (Isle of Man)"); /*United Kingdom*/ + init.put("23418","Cloud9"); /*United Kingdom*/ + init.put("23403","Jersey Telenet"); /*United Kingdom*/ + init.put("23450","JT-Wave"); /*United Kingdom*/ + init.put("23458","Manx Telecom"); /*United Kingdom*/ + init.put("23401","MCom"); /*United Kingdom*/ + init.put("23402","O2"); /*United Kingdom*/ + init.put("23410","O2"); /*United Kingdom*/ + init.put("23411","O2"); /*United Kingdom*/ + init.put("23433","Orange"); /*United Kingdom*/ + init.put("23434","Orange"); /*United Kingdom*/ + init.put("23412","Railtrack"); /*United Kingdom*/ + init.put("23422","Routo Telecom"); /*United Kingdom*/ + init.put("23409","Sure Mobile"); /*United Kingdom*/ + init.put("23430","T-Mobile"); /*United Kingdom*/ + init.put("23419","Telaware"); /*United Kingdom*/ + init.put("234100","Tesco Mobile"); /*United Kingdom*/ + init.put("23477","Unknown"); /*United Kingdom*/ + init.put("23431","Virgin"); /*United Kingdom*/ + init.put("23432","Virgin"); /*United Kingdom*/ + init.put("23415","Vodafone"); /*United Kingdom*/ + init.put("310880","Advantage"); /*United States*/ + init.put("310850","Aeris"); /*United States*/ + init.put("310640","Airadigm"); /*United States*/ + init.put("310780","Airlink PCS"); /*United States*/ + init.put("310034","Airpeak"); /*United States*/ + init.put("310510","Airtel"); /*United States*/ + init.put("310430","Alaska Digitel"); /*United States*/ + init.put("310500","Alltel"); /*United States*/ + init.put("310590","Alltel"); /*United States*/ + init.put("310630","AmeriLink PCS"); /*United States*/ + init.put("310038","AT&T"); /*United States*/ + init.put("310090","AT&T"); /*United States*/ + init.put("310150","AT&T"); /*United States*/ + init.put("310170","AT&T"); /*United States*/ + init.put("310410","AT&T"); /*United States*/ + init.put("310560","AT&T"); /*United States*/ + init.put("310680","AT&T"); /*United States*/ + init.put("310380","AT&T Mobility"); /*United States*/ + init.put("310980","AT&T Mobility"); /*United States*/ + init.put("310990","AT&T Mobility"); /*United States*/ + init.put("310830","Caprock"); /*United States*/ + init.put("310350","Carolina Phone"); /*United States*/ + init.put("311130","Cell One Amarillo"); /*United States*/ + init.put("310320","Cellular One"); /*United States*/ + init.put("310440","Cellular One"); /*United States*/ + init.put("310390","Cellular One of East Texas"); /*United States*/ + init.put("311190","Cellular Properties"); /*United States*/ + init.put("310030","Centennial"); /*United States*/ + init.put("311010","Chariton Valley"); /*United States*/ + init.put("310570","Chinook Wireless"); /*United States*/ + init.put("310480","Choice Phone"); /*United States*/ + init.put("311120","Choice Phone"); /*United States*/ + init.put("310420","Cincinnati Bell"); /*United States*/ + init.put("311180","Cingular Wireless"); /*United States*/ + init.put("310620","Coleman County Telecom"); /*United States*/ + init.put("311040","Commnet Wireless"); /*United States*/ + init.put("310040","Concho"); /*United States*/ + init.put("310690","Conestoga"); /*United States*/ + init.put("310060","Consolidated Telcom"); /*United States*/ + init.put("310740","Convey"); /*United States*/ + init.put("310080","Corr"); /*United States*/ + init.put("310016","Cricket Communications"); /*United States*/ + init.put("310940","Digital Cellular"); /*United States*/ + init.put("310190","Dutch Harbor"); /*United States*/ + init.put("311070","Easterbrooke"); /*United States*/ + init.put("311160","Endless Mountains Wireless"); /*United States*/ + init.put("310610","Epic Touch"); /*United States*/ + init.put("311060","Farmers Cellular"); /*United States*/ + init.put("311210","Farmers Cellular"); /*United States*/ + init.put("310311","Farmers Wireless"); /*United States*/ + init.put("310910","First Cellular"); /*United States*/ + init.put("310300","Get Mobile Inc"); /*United States*/ + init.put("310970","Globalstar"); /*United States*/ + init.put("311100","High Plains Wireless"); /*United States*/ + init.put("311110","High Plains Wireless"); /*United States*/ + init.put("310070","Highland Cellular"); /*United States*/ + init.put("310400","i CAN_GSM"); /*United States*/ + init.put("310770","i wireless"); /*United States*/ + init.put("311030","Indigo Wireless"); /*United States*/ + init.put("310650","Jasper"); /*United States*/ + init.put("311090","Long Lines Wireless"); /*United States*/ + init.put("310010","MCI"); /*United States*/ + init.put("310000","Mid-Tex Cellular"); /*United States*/ + init.put("311000","Mid-Tex Cellular"); /*United States*/ + init.put("311020","Missouri RSA 5 Partnership"); /*United States*/ + init.put("310013","MobileTel"); /*United States*/ + init.put("316010","Nextel"); /*United States*/ + init.put("310017","North Sight Communications Inc."); /*United States*/ + init.put("310670","Northstar"); /*United States*/ + init.put("310540","Oklahoma Western"); /*United States*/ + init.put("310870","PACE"); /*United States*/ + init.put("310760","Panhandle"); /*United States*/ + init.put("311170","PetroCom"); /*United States*/ + init.put("311080","Pine Cellular"); /*United States*/ + init.put("310790","PinPoint"); /*United States*/ + init.put("310100","Plateau Wireless"); /*United States*/ + init.put("310960","Plateau Wireless"); /*United States*/ + init.put("310110","PTI Pacifica"); /*United States*/ + init.put("310730","SeaMobile"); /*United States*/ + init.put("310046","SIMMETRY"); /*United States*/ + init.put("310460","Simmetry"); /*United States*/ + init.put("316011","Southern Communications Services"); /*United States*/ + init.put("310120","Sprint"); /*United States*/ + init.put("311140","Sprocket"); /*United States*/ + init.put("310490","SunCom"); /*United States*/ + init.put("310026","T-Mobile"); /*United States*/ + init.put("310160","T-Mobile"); /*United States*/ + init.put("310200","T-Mobile"); /*United States*/ + init.put("310210","T-Mobile"); /*United States*/ + init.put("310220","T-Mobile"); /*United States*/ + init.put("310230","T-Mobile"); /*United States*/ + init.put("310240","T-Mobile"); /*United States*/ + init.put("310250","T-Mobile"); /*United States*/ + init.put("310260","T-Mobile"); /*United States*/ + init.put("310270","T-Mobile"); /*United States*/ + init.put("310280","T-Mobile"); /*United States*/ + init.put("310290","T-Mobile"); /*United States*/ + init.put("310310","T-Mobile"); /*United States*/ + init.put("310330","T-Mobile"); /*United States*/ + init.put("310580","T-Mobile"); /*United States*/ + init.put("310660","T-Mobile"); /*United States*/ + init.put("310800","T-Mobile"); /*United States*/ + init.put("310900","Taylor"); /*United States*/ + init.put("310014","Testing"); /*United States*/ + init.put("310020","Union Telephone Company"); /*United States*/ + init.put("310520","VeriSign"); /*United States*/ + init.put("20404","Verizon"); /*United States*/ + init.put("246081","Verizon"); /*United States*/ + init.put("310004","Verizon"); /*United States*/ + init.put("310012","Verizon"); /*United States*/ + init.put("311480","Verizon"); /*United States*/ + init.put("310450","Viaero"); /*United States*/ + init.put("310180","West Central"); /*United States*/ + init.put("310530","West Virginia Wireless"); /*United States*/ + init.put("310340","Westlink"); /*United States*/ + init.put("311050","Wikes Cellular"); /*United States*/ + init.put("311150","Wilkes Cellular"); /*United States*/ + init.put("310890","Wireless Alliance"); /*United States*/ + init.put("310950","XIT Wireless"); /*United States*/ + init.put("74800","Ancel"); /*Uruguay*/ + init.put("74801","Ancel"); /*Uruguay*/ + init.put("74810","Claro"); /*Uruguay*/ + init.put("74807","Movistar"); /*Uruguay*/ + init.put("43404","Beeline"); /*Uzbekistan*/ + init.put("43401","Buztel"); /*Uzbekistan*/ + init.put("43407","MTS"); /*Uzbekistan*/ + init.put("43406","Perfectum Mobile"); /*Uzbekistan*/ + init.put("43405","Ucell"); /*Uzbekistan*/ + init.put("43402","Uzmacom"); /*Uzbekistan*/ + init.put("54101","SMILE"); /*Vanuatu*/ + init.put("73401","Digitel"); /*Venezuela*/ + init.put("73402","Digitel"); /*Venezuela*/ + init.put("73403","Digitel"); /*Venezuela*/ + init.put("73406","Movilnet"); /*Venezuela*/ + init.put("73404","movistar"); /*Venezuela*/ + init.put("45208","3G EVNTelecom"); /*Vietnam*/ + init.put("45207","Beeline VN"); /*Vietnam*/ + init.put("45206","E-Mobile"); /*Vietnam*/ + init.put("45205","HT Mobile"); /*Vietnam*/ + init.put("45201","MobiFone"); /*Vietnam*/ + init.put("45203","S-Fone"); /*Vietnam*/ + init.put("45204","Viettel Mobile"); /*Vietnam*/ + init.put("45202","Vinaphone"); /*Vietnam*/ + init.put("376350","C&W"); /*Wyspy Turks i Caicos*/ + init.put("33805","Digicel"); /*Wyspy Turks i Caicos*/ + init.put("376352","Islandcom"); /*Wyspy Turks i Caicos*/ + init.put("42104","HiTS-UNITEL"); /*Yemen*/ + init.put("42102","MTN"); /*Yemen*/ + init.put("42101","SabaFon"); /*Yemen*/ + init.put("42103","Yemen Mobile"); /*Yemen*/ + init.put("64502","MTN"); /*Zambia*/ + init.put("64501","Zain"); /*Zambia*/ + init.put("64503","ZAMTEL"); /*Zambia*/ + init.put("64804","Econet"); /*Zimbabwe*/ + init.put("64801","Net*One"); /*Zimbabwe*/ + init.put("64803","Telecel"); /*Zimbabwe*/ + + operators = Collections.unmodifiableMap(init); + } + + public static String operatorReplace(String response){ + if(operators == null){ + initList(); + } + return operators.containsKey(response) ? operators.get(response) : response; + } +} diff --git a/src/java/com/android/internal/telephony/QualcommMSIM42RIL.java b/src/java/com/android/internal/telephony/QualcommMSIM42RIL.java new file mode 100644 index 0000000000..46d0465149 --- /dev/null +++ b/src/java/com/android/internal/telephony/QualcommMSIM42RIL.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012-2013 The CyanogenMod 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.content.Context; +import android.os.Message; + +/** + * Backwards compatible RIL implementation for Qualcomm MSIM based + * radios. Android 4.3 added the CELL_INFO_LIST commands, displacing several + * command ids already used in pre-4.3 RILs. + * + * {@hide} + */ +public class QualcommMSIM42RIL extends RIL implements CommandsInterface { + + static final int RIL_REQUEST_IMS_REGISTRATION_STATE = 109; + static final int RIL_REQUEST_IMS_SEND_SMS = 110; + static final int RIL_REQUEST_GET_DATA_CALL_PROFILE = 111; + static final int RIL_REQUEST_SET_UICC_SUBSCRIPTION = 118; + static final int RIL_REQUEST_SET_DATA_SUBSCRIPTION = 119; + static final int RIL_REQUEST_GET_UICC_SUBSCRIPTION = 120; + static final int RIL_REQUEST_GET_DATA_SUBSCRIPTION = 121; + static final int RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1036; + static final int RIL_UNSOL_TETHERED_MODE_STATE_CHANGED = 1037; + + public QualcommMSIM42RIL(Context context, int networkMode, + int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + /** + * {@inheritDoc} + */ + @Override + public void getCellInfoList(Message result) { + if (RILJ_LOGD) riljLog("[STUB] > getCellInfoList"); + } + + /** + * {@inheritDoc} + */ + @Override + public void setCellInfoListRate(int rateInMillis, Message response) { + if (RILJ_LOGD) riljLog("[STUB] > setCellInfoListRate"); + } + + public void getImsRegistrationState(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_IMS_REGISTRATION_STATE, result); + + if (RILJ_LOGD) { + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + } + send(rr); + } + + public void setUiccSubscription(int slotId, int appIndex, int subId, + int subStatus, Message result) { + //Note: This RIL request is also valid for SIM and RUIM (ICC card) + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_UICC_SUBSCRIPTION, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " slot: " + slotId + " appIndex: " + appIndex + + " subId: " + subId + " subStatus: " + subStatus); + + rr.mParcel.writeInt(slotId); + rr.mParcel.writeInt(appIndex); + rr.mParcel.writeInt(subId); + rr.mParcel.writeInt(subStatus); + + send(rr); + } + + public void setDataSubscription(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_DATA_SUBSCRIPTION, result); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); + } + + public void + getDataCallProfile(int appType, Message result) { + RILRequest rr = RILRequest.obtain( + RIL_REQUEST_GET_DATA_CALL_PROFILE, result); + + // count of ints + rr.mParcel.writeInt(1); + rr.mParcel.writeInt(appType); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + appType); + + send(rr); + } + +} diff --git a/src/java/com/android/internal/telephony/QualcommSharedRIL.java b/src/java/com/android/internal/telephony/QualcommSharedRIL.java new file mode 100644 index 0000000000..e62ed5c769 --- /dev/null +++ b/src/java/com/android/internal/telephony/QualcommSharedRIL.java @@ -0,0 +1,615 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * Copyright (C) 2013 The OmniROM 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 static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.os.AsyncResult; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Parcel; +import android.telephony.SmsMessage; +import android.os.SystemProperties; +import android.telephony.SignalStrength; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.dataconnection.DataCallResponse; +import com.android.internal.telephony.dataconnection.DcFailCause; + +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.uicc.IccCardStatus; + +import java.util.ArrayList; + +/** + * Custom Qualcomm No SimReady RIL using the latest Uicc stack + * + * {@hide} + */ +public class QualcommSharedRIL extends RIL implements CommandsInterface { + protected HandlerThread mIccThread; + protected IccHandler mIccHandler; + protected String mAid; + protected boolean mUSIM = false; + protected String[] mLastDataIface = new String[20]; + boolean RILJ_LOGV = true; + boolean RILJ_LOGD = true; + boolean skipCdmaSubcription = needsOldRilFeature("skipCdmaSubcription"); + + private final int RIL_INT_RADIO_OFF = 0; + private final int RIL_INT_RADIO_UNAVALIABLE = 1; + private final int RIL_INT_RADIO_ON = 2; + private final int RIL_INT_RADIO_ON_NG = 10; + private final int RIL_INT_RADIO_ON_HTC = 13; + + + public QualcommSharedRIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + mSetPreferredNetworkType = -1; + mQANElements = 5; + } + + @Override public void + supplyIccPin2(String pin, Message result) { + supplyIccPin2ForApp(pin, mAid, result); + } + + @Override public void + changeIccPin2(String oldPin2, String newPin2, Message result) { + changeIccPin2ForApp(oldPin2, newPin2, mAid, result); + } + + @Override public void + supplyIccPuk(String puk, String newPin, Message result) { + supplyIccPukForApp(puk, newPin, mAid, result); + } + + @Override public void + supplyIccPuk2(String puk2, String newPin2, Message result) { + supplyIccPuk2ForApp(puk2, newPin2, mAid, result); + } + + @Override + public void + queryFacilityLock(String facility, String password, int serviceClass, + Message response) { + queryFacilityLockForApp(facility, password, serviceClass, mAid, response); + } + + @Override + public void + setFacilityLock (String facility, boolean lockState, String password, + int serviceClass, Message response) { + setFacilityLockForApp(facility, lockState, password, serviceClass, mAid, response); + } + + @Override + public void + getIMSI(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); + + rr.mParcel.writeInt(1); + rr.mParcel.writeString(mAid); + + if (RILJ_LOGD) riljLog(rr.serialString() + + "> getIMSI:RIL_REQUEST_GET_IMSI " + + RIL_REQUEST_GET_IMSI + + " aid: " + mAid + + " " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + public void + iccIO (int command, int fileid, String path, int p1, int p2, int p3, + String data, String pin2, Message result) { + //Note: This RIL request has not been renamed to ICC, + // but this request is also valid for SIM and RUIM + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SIM_IO, result); + + if (mUSIM) + path = path.replaceAll("7F20$","7FFF"); + + rr.mParcel.writeInt(command); + rr.mParcel.writeInt(fileid); + rr.mParcel.writeString(path); + rr.mParcel.writeInt(p1); + rr.mParcel.writeInt(p2); + rr.mParcel.writeInt(p3); + rr.mParcel.writeString(data); + rr.mParcel.writeString(pin2); + rr.mParcel.writeString(mAid); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + + " aid: " + mAid + " " + + requestToString(rr.mRequest) + + " 0x" + Integer.toHexString(command) + + " 0x" + Integer.toHexString(fileid) + " " + + " path: " + path + "," + + p1 + "," + p2 + "," + p3); + + send(rr); + } + + @Override + protected Object + responseIccCardStatus(Parcel p) { + IccCardApplicationStatus ca; + + IccCardStatus status = new IccCardStatus(); + status.setCardState(p.readInt()); + status.setUniversalPinState(p.readInt()); + status.mGsmUmtsSubscriptionAppIndex = p.readInt(); + status.mCdmaSubscriptionAppIndex = p.readInt(); + status.mImsSubscriptionAppIndex = p.readInt(); + + int numApplications = p.readInt(); + + // limit to maximum allowed applications + if (numApplications > IccCardStatus.CARD_MAX_APPS) { + numApplications = IccCardStatus.CARD_MAX_APPS; + } + status.mApplications = new IccCardApplicationStatus[numApplications]; + + for (int i = 0; i < numApplications; i++) { + ca = new IccCardApplicationStatus(); + ca.app_type = ca.AppTypeFromRILInt(p.readInt()); + ca.app_state = ca.AppStateFromRILInt(p.readInt()); + ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt()); + ca.aid = p.readString(); + ca.app_label = p.readString(); + ca.pin1_replaced = p.readInt(); + ca.pin1 = ca.PinStateFromRILInt(p.readInt()); + ca.pin2 = ca.PinStateFromRILInt(p.readInt()); + if (!needsOldRilFeature("skippinpukcount")) { + p.readInt(); //remaining_count_pin1 + p.readInt(); //remaining_count_puk1 + p.readInt(); //remaining_count_pin2 + p.readInt(); //remaining_count_puk2 + } + status.mApplications[i] = ca; + } + int appIndex = -1; + if (mPhoneType == RILConstants.CDMA_PHONE && !skipCdmaSubcription) { + appIndex = status.mCdmaSubscriptionAppIndex; + Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); + } else { + appIndex = status.mGsmUmtsSubscriptionAppIndex; + Log.d(LOG_TAG, "This is a GSM PHONE " + appIndex); + } + + if (numApplications > 0) { + IccCardApplicationStatus application = status.mApplications[appIndex]; + mAid = application.aid; + mUSIM = application.app_type + == IccCardApplicationStatus.AppType.APPTYPE_USIM; + mSetPreferredNetworkType = mPreferredNetworkType; + + if (TextUtils.isEmpty(mAid)) + mAid = ""; + Log.d(LOG_TAG, "mAid " + mAid); + } + + return status; + } + + @Override + protected DataCallResponse getDataCallResponse(Parcel p, int version) { + DataCallResponse dataCall = new DataCallResponse(); + + boolean oldRil = needsOldRilFeature("datacall"); + + if (!oldRil && version < 5) { + return super.getDataCallResponse(p, version); + } else if (!oldRil) { + dataCall.version = version; + dataCall.status = p.readInt(); + dataCall.suggestedRetryTime = p.readInt(); + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + dataCall.ifname = p.readString(); + if ((dataCall.status == DcFailCause.NONE.getErrorCode()) && + TextUtils.isEmpty(dataCall.ifname) && dataCall.active != 0) { + throw new RuntimeException("getDataCallResponse, no ifname"); + } + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + String dnses = p.readString(); + if (!TextUtils.isEmpty(dnses)) { + dataCall.dnses = dnses.split(" "); + } + String gateways = p.readString(); + if (!TextUtils.isEmpty(gateways)) { + dataCall.gateways = gateways.split(" "); + } + } else { + dataCall.version = 4; // was dataCall.version = version; + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + dataCall.ifname = mLastDataIface[dataCall.cid]; + p.readString(); // skip APN + + if (TextUtils.isEmpty(dataCall.ifname)) { + dataCall.ifname = mLastDataIface[0]; + } + + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + p.readInt(); // RadioTechnology + p.readInt(); // inactiveReason + + dataCall.dnses = new String[2]; + dataCall.dnses[0] = SystemProperties.get("net."+dataCall.ifname+".dns1"); + dataCall.dnses[1] = SystemProperties.get("net."+dataCall.ifname+".dns2"); + } + + return dataCall; + } + + @Override + protected Object + responseSetupDataCall(Parcel p) { + DataCallResponse dataCall; + + boolean oldRil = needsOldRilFeature("datacall"); + + if (!oldRil) + return super.responseSetupDataCall(p); + + dataCall = new DataCallResponse(); + dataCall.version = 4; + + dataCall.cid = 0; // Integer.parseInt(p.readString()); + p.readString(); + dataCall.ifname = p.readString(); + if ((dataCall.status == DcFailCause.NONE.getErrorCode()) && + TextUtils.isEmpty(dataCall.ifname) && dataCall.active != 0) { + throw new RuntimeException( + "RIL_REQUEST_SETUP_DATA_CALL response, no ifname"); + } + /* Use the last digit of the interface id as the cid */ + if (!needsOldRilFeature("singlepdp")) { + dataCall.cid = + Integer.parseInt(dataCall.ifname.substring(dataCall.ifname.length() - 1)); + } + + mLastDataIface[dataCall.cid] = dataCall.ifname; + + + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + + dataCall.dnses = new String[2]; + dataCall.dnses[0] = SystemProperties.get("net."+dataCall.ifname+".dns1"); + dataCall.dnses[1] = SystemProperties.get("net."+dataCall.ifname+".dns2"); + dataCall.active = 1; + dataCall.status = 0; + + return dataCall; + } + + @Override + public void getNeighboringCids(Message response) { + if (!getRadioState().isOn()) + return; + + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + public void setCurrentPreferredNetworkType() { + if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType: " + mSetPreferredNetworkType); + setPreferredNetworkType(mSetPreferredNetworkType, null); + } + + @Override + public void setPreferredNetworkType(int networkType , Message response) { + /** + * If not using a USIM, ignore LTE mode and go to 3G + */ + if (!mUSIM && networkType == RILConstants.NETWORK_MODE_LTE_GSM_WCDMA && + mSetPreferredNetworkType >= RILConstants.NETWORK_MODE_WCDMA_PREF) { + networkType = RILConstants.NETWORK_MODE_WCDMA_PREF; + } + mSetPreferredNetworkType = networkType; + + super.setPreferredNetworkType(networkType, response); + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + boolean oldRil = needsOldRilFeature("signalstrength"); + boolean noLte = false; + + /* TODO: Add SignalStrength class to match RIL_SignalStrength */ + response = new int[numInts]; + for (int i = 0 ; i < numInts ; i++) { + if ((oldRil || noLte) && i > 6 && i < 12) { + response[i] = -1; + } else { + response[i] = p.readInt(); + } + if (i == 7 && response[i] == 99) { + response[i] = -1; + noLte = true; + } + } + return new SignalStrength(response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7],response[8], response[9], response[10], response[11], true); + } + + @Override + protected Object getOverridenRequestResponse(int mRequest, Parcel p) { + switch(mRequest) { + case 104: return responseInts(p); // RIL_REQUEST_VOICE_RADIO_TECH + case 105: return responseInts(p); // RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE + case 106: return responseStrings(p); // RIL_REQUEST_CDMA_PRL_VERSION + case 107: return responseInts(p); // RIL_REQUEST_IMS_REGISTRATION_STATE + case 220: return responseStrings(p); //RIL_REQUEST_BASEBAND_VERSION + default: return null; + } + } + + @Override + protected void + processUnsolicited (Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + /* Assume devices needing the "datacall" GB-compatibility flag are + * running GB RILs, so skip 1031-1034 for those */ + if (needsOldRilFeature("datacall")) { + switch(response) { + case 1031: + case 1032: + case 1033: + case 1034: + ret = responseVoid(p); + return; + } + } + + switch(response) { + //case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; + case 1035: ret = responseVoid(p); break; // RIL_UNSOL_VOICE_RADIO_TECH_CHANGED + case 1036: ret = responseVoid(p); break; // RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED + case 1037: ret = responseVoid(p); break; // RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE + case 1038: ret = responseVoid(p); break; // RIL_UNSOL_DATA_NETWORK_STATE_CHANGED + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: + int state = p.readInt(); + setRadioStateFromRILInt(state); + break; + case RIL_UNSOL_RIL_CONNECTED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); + break; + case 1035: + case 1036: + break; + case 1037: // RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mExitEmergencyCallbackModeRegistrants != null) { + mExitEmergencyCallbackModeRegistrants.notifyRegistrants( + new AsyncResult (null, null, null)); + } + break; + case 1038: + break; + } + } + + private void setRadioStateFromRILInt (int stateCode) { + CommandsInterface.RadioState radioState; + HandlerThread handlerThread; + Looper looper; + IccHandler iccHandler; + + switch (stateCode) { + case RIL_INT_RADIO_OFF: + radioState = CommandsInterface.RadioState.RADIO_OFF; + if (mIccHandler != null) { + mIccThread = null; + mIccHandler = null; + } + break; + case RIL_INT_RADIO_UNAVALIABLE: + radioState = CommandsInterface.RadioState.RADIO_UNAVAILABLE; + break; + case RIL_INT_RADIO_ON: + case RIL_INT_RADIO_ON_NG: + case RIL_INT_RADIO_ON_HTC: + if (mIccHandler == null) { + handlerThread = new HandlerThread("IccHandler"); + mIccThread = handlerThread; + + mIccThread.start(); + + looper = mIccThread.getLooper(); + mIccHandler = new IccHandler(this,looper); + mIccHandler.run(); + } + radioState = CommandsInterface.RadioState.RADIO_ON; + break; + default: + throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); + } + + setRadioState (radioState); + } + + class IccHandler extends Handler implements Runnable { + private static final int EVENT_RADIO_ON = 1; + private static final int EVENT_ICC_STATUS_CHANGED = 2; + private static final int EVENT_GET_ICC_STATUS_DONE = 3; + private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 4; + + private RIL mRil; + private boolean mRadioOn = false; + + public IccHandler (RIL ril, Looper looper) { + super (looper); + mRil = ril; + } + + public void handleMessage (Message paramMessage) { + switch (paramMessage.what) { + case EVENT_RADIO_ON: + mRadioOn = true; + Log.d(LOG_TAG, "Radio on -> Forcing sim status update"); + sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); + break; + case EVENT_GET_ICC_STATUS_DONE: + AsyncResult asyncResult = (AsyncResult) paramMessage.obj; + if (asyncResult.exception != null) { + Log.e (LOG_TAG, "IccCardStatusDone shouldn't return exceptions!", asyncResult.exception); + break; + } + IccCardStatus status = (IccCardStatus) asyncResult.result; + if (status.mApplications == null || status.mApplications.length == 0) { + if (!mRil.getRadioState().isOn()) { + break; + } + + mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); + } else { + int appIndex = -1; + if (mPhoneType == RILConstants.CDMA_PHONE && !skipCdmaSubcription) { + appIndex = status.mCdmaSubscriptionAppIndex; + Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); + } else { + appIndex = status.mGsmUmtsSubscriptionAppIndex; + Log.d(LOG_TAG, "This is a GSM PHONE " + appIndex); + } + + IccCardApplicationStatus application = status.mApplications[appIndex]; + IccCardApplicationStatus.AppState app_state = application.app_state; + IccCardApplicationStatus.AppType app_type = application.app_type; + + switch (app_state) { + case APPSTATE_PIN: + case APPSTATE_PUK: + switch (app_type) { + case APPTYPE_SIM: + case APPTYPE_USIM: + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); + break; + default: + Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); + return; + } + break; + case APPSTATE_READY: + switch (app_type) { + case APPTYPE_SIM: + case APPTYPE_USIM: + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); + break; + default: + Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); + return; + } + break; + default: + return; + } + } + break; + case EVENT_ICC_STATUS_CHANGED: + if (mRadioOn) { + Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); + mRil.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, paramMessage.obj)); + } else { + Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED while radio is not ON. Ignoring"); + } + break; + case EVENT_RADIO_OFF_OR_UNAVAILABLE: + mRadioOn = false; + // disposeCards(); // to be verified; + default: + Log.e(LOG_TAG, " Unknown Event " + paramMessage.what); + break; + } + } + + public void run () { + mRil.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); + Message msg = obtainMessage(EVENT_RADIO_ON); + mRil.getIccCardStatus(msg); + } + } + + + @Override + public void + setNetworkSelectionModeManual(String operatorNumeric, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + operatorNumeric); + + rr.mParcel.writeInt(2); + rr.mParcel.writeString(operatorNumeric); + rr.mParcel.writeString("NOCHANGE"); + + send(rr); + } +} diff --git a/src/java/com/android/internal/telephony/SamsungCDMAv6RIL.java b/src/java/com/android/internal/telephony/SamsungCDMAv6RIL.java new file mode 100644 index 0000000000..2b6259988d --- /dev/null +++ b/src/java/com/android/internal/telephony/SamsungCDMAv6RIL.java @@ -0,0 +1,802 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2011, 2012 The CyanogenMod Project + * Copyright (C) 2013 The OmniROM 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 java.util.ArrayList; +import java.util.Collections; +import java.lang.Runtime; +import java.io.IOException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Message; +import android.os.AsyncResult; +import android.os.Parcel; +import android.os.SystemProperties; +import android.telephony.PhoneNumberUtils; +import android.telephony.SignalStrength; +import android.telephony.SmsManager; +import android.telephony.SmsMessage; +import static com.android.internal.telephony.RILConstants.*; + +import com.android.internal.telephony.CallForwardInfo; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.gsm.SuppServiceNotification; +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.uicc.IccCardStatus; +import com.android.internal.telephony.uicc.IccUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.SmsResponse; +import com.android.internal.telephony.cdma.CdmaCallWaitingNotification; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; +import com.android.internal.telephony.cdma.SignalToneUtil; +import com.android.internal.telephony.dataconnection.DataCallResponse; +import com.android.internal.telephony.dataconnection.DcFailCause; + +import android.text.TextUtils; +import android.telephony.Rlog; + +public class SamsungCDMAv6RIL extends RIL implements CommandsInterface { + + public SamsungCDMAv6RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + // SAMSUNG SGS STATES + static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007; + static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008; + static final int RIL_UNSOL_GPS_NOTI = 11009; + static final int RIL_UNSOL_AM = 11010; + static final int RIL_UNSOL_DATA_SUSPEND_RESUME = 11012; + static final int RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL = 11011; + static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; + static final int RIL_REQUEST_DIAL_EMERGENCY = 10016; + + static String + requestToString(int request) { + switch (request) { + case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY"; + default: return RIL.requestToString(request); + } + } + + static String + samsungResponseToString(int request) + { + switch(request) { + // SAMSUNG STATES + case RIL_UNSOL_AM: return "RIL_UNSOL_AM"; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: return "RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL"; + case RIL_UNSOL_DATA_SUSPEND_RESUME: return "RIL_UNSOL_DATA_SUSPEND_RESUME"; + default: return ""; + } +} + + protected void samsungUnsljLogRet(int response, Object ret) { + riljLog("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret)); + } + + @Override + public void + setRadioPower(boolean on, Message result) { + boolean allow = SystemProperties.getBoolean("persist.ril.enable", true); + if (!allow) { + return; + } + + RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); + + if (on) { + rr.mParcel.writeInt(1); + rr.mParcel.writeInt(1); + } else { + rr.mParcel.writeInt(2); + rr.mParcel.writeInt(0); + rr.mParcel.writeInt(0); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); + } + + @Override + protected Object getOverridenRequestResponse(int mRequest, Parcel p) { + switch(mRequest) { + case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return responseLastCallFailCause(p); + case RIL_REQUEST_VOICE_REGISTRATION_STATE: return responseVoiceRegistrationState(p); + case RIL_REQUEST_CDMA_SUBSCRIPTION: return responseCdmaSubscription(p); + default: return null; + } + } + + @Override + protected boolean hasSamsungSendSmsFix() { return true; } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr; + + rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + rr.mParcel.writeString(address); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); // UUS information is absent + + if (uusInfo == null) { + rr.mParcel.writeInt(0); // UUS information is absent + } else { + rr.mParcel.writeInt(1); // UUS information is present + rr.mParcel.writeInt(uusInfo.getType()); + rr.mParcel.writeInt(uusInfo.getDcs()); + rr.mParcel.writeByteArray(uusInfo.getUserData()); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + dialEmergencyCall(String address, int clirMode, Message result) { + RILRequest rr; + Rlog.v(RILJ_LOG_TAG, "Emergency dial: " + address); + + rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result); + rr.mParcel.writeString(address + "/"); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); + rr.mParcel.writeInt(0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + protected void + processUnsolicited (Parcel p) { + int response; + Object ret; + int dataPosition = p.dataPosition(); + + response = p.readInt(); + + switch(response) { + /* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/' + */ + + case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_HSDPA_STATE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break; + case RIL_UNSOL_DEVICE_READY_NOTI: ret = responseVoid(p); break; + case RIL_UNSOL_GPS_NOTI: ret = responseVoid(p); break; // Ignored in TW RIL. + // SAMSUNG STATES + case RIL_UNSOL_AM: ret = responseString(p); break; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: ret = responseVoid(p); break; + case RIL_UNSOL_DATA_SUSPEND_RESUME: ret = responseInts(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseString(p); break; + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_HSDPA_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + boolean newHsdpa = ((int[])ret)[0] == 1; + String curState = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE); + boolean curHsdpa = false; + + if (curState.equals("HSDPA:9")) { + curHsdpa = true; + } else if (!curState.equals("UMTS:3")) { + // Don't send poll request if not on 3g + break; + } + + if (curHsdpa != newHsdpa) { + mVoiceNetworkStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + } + break; + + case RIL_UNSOL_NITZ_TIME_RECEIVED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + String nitz = (String)ret; + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED length = " + + nitz.split("[/:,+-]").length); + + // remove the tailing information that samsung added to the string + if(nitz.split("[/:,+-]").length >= 9) + nitz = nitz.substring(0,(nitz.lastIndexOf(","))); + + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED striped nitz = " + + nitz); + + result[0] = nitz; + result[1] = Long.valueOf(nitzReceiveTime); + + if (mNITZTimeRegistrant != null) { + + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = nitz; + } + break; + + case RIL_UNSOL_SIGNAL_STRENGTH: + // Note this is set to "verbose" because it happens + // frequently + if (RILJ_LOGV) unsljLogvRet(response, ret); + + if (mSignalStrengthRegistrant != null) { + mSignalStrengthRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_INFO_REC: + ArrayList listInfoRecs; + + try { + listInfoRecs = (ArrayList)ret; + } catch (ClassCastException e) { + Rlog.e(RILJ_LOG_TAG, "Unexpected exception casting to listInfoRecs", e); + break; + } + + for (CdmaInformationRecords rec : listInfoRecs) { + if (RILJ_LOGD) unsljLogRet(response, rec); + notifyRegistrantsCdmaInfoRec(rec); + } + break; + + case RIL_UNSOL_RIL_CONNECTED: + // FIXME: Processing this state breaks data call. + break; + // SAMSUNG STATES + case RIL_UNSOL_AM: + String amString = (String) ret; + Rlog.d(RILJ_LOG_TAG, "Executing AM: " + amString); + + try { + Runtime.getRuntime().exec("am " + amString); + } catch (IOException e) { + e.printStackTrace(); + Rlog.e(RILJ_LOG_TAG, "am " + amString + " could not be executed."); + } + break; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + case RIL_UNSOL_DATA_SUSPEND_RESUME: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + } + } + + @Override + protected Object + responseCallList(Parcel p) { + int num; + boolean isVideo; + ArrayList response; + DriverCall dc; + int dataAvail = p.dataAvail(); + int pos = p.dataPosition(); + int size = p.dataSize(); + + Rlog.d(RILJ_LOG_TAG, "Parcel size = " + size); + Rlog.d(RILJ_LOG_TAG, "Parcel pos = " + pos); + Rlog.d(RILJ_LOG_TAG, "Parcel dataAvail = " + dataAvail); + + num = p.readInt(); + response = new ArrayList(num); + + for (int i = 0 ; i < num ; i++) { + dc = new SamsungDriverCall(); + + dc.state = DriverCall.stateFromCLCC(p.readInt()); + dc.index = p.readInt(); + dc.TOA = p.readInt(); + dc.isMpty = (0 != p.readInt()); + dc.isMT = (0 != p.readInt()); + dc.als = p.readInt(); + dc.isVoice = (0 != p.readInt()); + isVideo = (0 != p.readInt()); + dc.isVoicePrivacy = (0 != p.readInt()); + dc.number = p.readString(); + int np = p.readInt(); + dc.numberPresentation = DriverCall.presentationFromCLIP(np); + dc.name = p.readString(); + dc.namePresentation = p.readInt(); + int uusInfoPresent = p.readInt(); + + Rlog.d(RILJ_LOG_TAG, "state = " + dc.state); + Rlog.d(RILJ_LOG_TAG, "index = " + dc.index); + Rlog.d(RILJ_LOG_TAG, "state = " + dc.TOA); + Rlog.d(RILJ_LOG_TAG, "isMpty = " + dc.isMpty); + Rlog.d(RILJ_LOG_TAG, "isMT = " + dc.isMT); + Rlog.d(RILJ_LOG_TAG, "als = " + dc.als); + Rlog.d(RILJ_LOG_TAG, "isVoice = " + dc.isVoice); + Rlog.d(RILJ_LOG_TAG, "isVideo = " + isVideo); + Rlog.d(RILJ_LOG_TAG, "number = " + dc.number); + Rlog.d(RILJ_LOG_TAG, "numberPresentation = " + np); + Rlog.d(RILJ_LOG_TAG, "name = " + dc.name); + Rlog.d(RILJ_LOG_TAG, "namePresentation = " + dc.namePresentation); + Rlog.d(RILJ_LOG_TAG, "uusInfoPresent = " + uusInfoPresent); + + if (uusInfoPresent == 1) { + dc.uusInfo = new UUSInfo(); + dc.uusInfo.setType(p.readInt()); + dc.uusInfo.setDcs(p.readInt()); + byte[] userData = p.createByteArray(); + dc.uusInfo.setUserData(userData); + Rlog + .v(RILJ_LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : NOT present!"); + } + + // Make sure there's a leading + on addresses with a TOA of 145 + dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA); + + response.add(dc); + + if (dc.isVoicePrivacy) { + mVoicePrivacyOnRegistrants.notifyRegistrants(); + Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is enabled"); + } else { + mVoicePrivacyOffRegistrants.notifyRegistrants(); + Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is disabled"); + } + } + + Collections.sort(response); + + return response; + } + + @Override + protected DataCallResponse getDataCallResponse(Parcel p, int version) { + DataCallResponse dataCall = new DataCallResponse(); + + dataCall.version = version; + dataCall.status = p.readInt(); + dataCall.suggestedRetryTime = p.readInt(); + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + dataCall.ifname = SystemProperties.get("net.cdma.ppp.interface"); + if ((dataCall.status == DcFailCause.NONE.getErrorCode()) && + TextUtils.isEmpty(dataCall.ifname)) { + throw new RuntimeException("getDataCallResponse, no ifname"); + } + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + String dnses = p.readString(); + if (!TextUtils.isEmpty(dnses)) { + dataCall.dnses = dnses.split(" "); + } + String gateways = p.readString(); + if (!TextUtils.isEmpty(gateways)) { + dataCall.gateways = gateways.split(" "); + } + return dataCall; + } + + protected Object + responseLastCallFailCause(Parcel p) { + int response[] = (int[])responseInts(p); + + if (response.length > 0 && + response[0] == com.android.internal.telephony.cdma.CallFailCause.ERROR_UNSPECIFIED) { + + // Far-end hangup returns ERROR_UNSPECIFIED, which shows "Call Lost" dialog. + Rlog.d(RILJ_LOG_TAG, "Overriding ERROR_UNSPECIFIED fail cause with NORMAL_CLEARING."); + response[0] = com.android.internal.telephony.cdma.CallFailCause.NORMAL_CLEARING; + } + + return response; + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + response = new int[numInts]; + for (int i = 0 ; i < 7 ; i++) { + response[i] = p.readInt(); + } + + if(response[3] < 0){ + response[3] = -response[3]; + } + // Scale cdmaDbm so Samsung's -95..-105 range for SIGNAL_STRENGTH_POOR + // fits in AOSP's -95..-100 range + if(response[2] > 95){ + // Rlog.d(RILJ_LOG_TAG, "SignalStrength: Scaling cdmaDbm \"" + response[2] + "\" for smaller SIGNAL_STRENGTH_POOR bucket."); + response[2] = ((response[2]-96)/2)+96; + } + // Framework takes care of the rest for us. + + SignalStrength signalStrength = new SignalStrength( + response[0], response[1], response[2], response[3], response[4], + response[5], response[6], false); + return signalStrength; + } + + protected Object + responseVoiceRegistrationState(Parcel p) { + String response[] = (String[])responseStrings(p); + + // These values are provided in hex, convert to dec. + response[4] = Integer.toString(Integer.parseInt(response[4], 16)); // baseStationId + response[5] = Integer.toString(Integer.parseInt(response[5], 16)); // baseStationLatitude + response[6] = Integer.toString(Integer.parseInt(response[6], 16)); // baseStationLongitude + + return response; + } + + @Override + protected Object + responseGetPreferredNetworkType(Parcel p) { + int [] response = (int[]) responseInts(p); + return response; + } + + @Override + protected Object + responseSetupDataCall(Parcel p) { + DataCallResponse dataCall = new DataCallResponse(); + String strings[] = (String []) responseStrings(p); + + if (strings.length >= 2) { + dataCall.cid = Integer.parseInt(strings[0]); + + // We're responsible for starting/stopping the pppd_cdma service. + if (!startPppdCdmaService(strings[1])) { + // pppd_cdma service didn't respond timely. + dataCall.status = DcFailCause.ERROR_UNSPECIFIED.getErrorCode(); + return dataCall; + } + + // pppd_cdma service responded, pull network parameters set by ip-up script. + dataCall.ifname = SystemProperties.get("net.cdma.ppp.interface"); + String ifprop = "net." + dataCall.ifname; + + dataCall.addresses = new String[] {SystemProperties.get(ifprop + ".local-ip")}; + dataCall.gateways = new String[] {SystemProperties.get(ifprop + ".remote-ip")}; + dataCall.dnses = new String[] {SystemProperties.get(ifprop + ".dns1"), + SystemProperties.get(ifprop + ".dns2")}; + } else { + // On rare occasion the pppd_cdma service is left active from a stale + // session, causing the data call setup to fail. Make sure that pppd_cdma + // is stopped now, so that the next setup attempt may succeed. + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=0 to make sure pppd_cdma is stopped."); + SystemProperties.set("ril.cdma.data_state", "0"); + + dataCall.status = DcFailCause.ERROR_UNSPECIFIED.getErrorCode(); // Who knows? + } + + return dataCall; + } + + private boolean startPppdCdmaService(String ttyname) { + SystemProperties.set("net.cdma.datalinkinterface", ttyname); + + // Connecting: Set ril.cdma.data_state=1 to (re)start pppd_cdma service, + // which responds by setting ril.cdma.data_state=2 once connection is up. + SystemProperties.set("ril.cdma.data_state", "1"); + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=1, waiting for ril.cdma.data_state=2."); + + // Typically takes < 200 ms on my Epic, so sleep in 100 ms intervals. + for (int i = 0; i < 10; i++) { + try {Thread.sleep(100);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Rlog.d(RILJ_LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Taking > 1 s here, try up to 10 s, which is hopefully long enough. + for (int i = 1; i < 10; i++) { + try {Thread.sleep(1000);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Rlog.d(RILJ_LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Rlog.d(RILJ_LOG_TAG, "Didn't get ril.cdma.data_state=2 timely, aborting."); + SystemProperties.set("ril.cdma.data_state", "0"); + + return false; + } + + @Override + public void + deactivateDataCall(int cid, int reason, Message result) { + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=0."); + SystemProperties.set("ril.cdma.data_state", "0"); + + super.deactivateDataCall(cid, reason, result); + } + + protected Object + responseCdmaSubscription(Parcel p) { + String response[] = (String[])responseStrings(p); + + if (response.length == 4) { + // PRL version is missing in subscription parcel, add it from properties. + String prlVersion = SystemProperties.get("ril.prl_ver_1").split(":")[1]; + response = new String[] {response[0], response[1], response[2], + response[3], prlVersion}; + } + + return response; + } + + // Workaround for Samsung CDMA "ring of death" bug: + // + // Symptom: As soon as the phone receives notice of an incoming call, an + // audible "old fashioned ring" is emitted through the earpiece and + // persists through the duration of the call, or until reboot if the call + // isn't answered. + // + // Background: The CDMA telephony stack implements a number of "signal info + // tones" that are locally generated by ToneGenerator and mixed into the + // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests. + // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the + // radio just prior to notice of an incoming call when the voice call + // path is muted. CallNotifier is responsible for stopping all signal + // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a + // "new ringing connection", prior to unmuting the voice call path. + // + // Problem: CallNotifier's incoming call path is designed to minimize + // latency to notify users of incoming calls ASAP. Thus, + // SignalInfoTonePlayer requests are handled asynchronously by spawning a + // one-shot thread for each. Unfortunately the ToneGenerator API does + // not provide a mechanism to specify an ordering on requests, and thus, + // unexpected thread interleaving may result in ToneGenerator processing + // them in the opposite order that CallNotifier intended. In this case, + // playing the "signal off" tone first, followed by playing the "old + // fashioned ring" indefinitely. + // + // Solution: An API change to ToneGenerator is required to enable + // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any + // request that's older than the most recent observed). Such a change, + // or another appropriate fix should be implemented in AOSP first. + // + // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio, + // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and + // drop it so it's never seen by CallNotifier. If other signal tones are + // observed to cause this problem, they should be dropped here as well. + @Override + protected void + notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { + final int response = RIL_UNSOL_CDMA_INFO_REC; + + if (infoRec.record instanceof CdmaSignalInfoRec) { + CdmaSignalInfoRec sir = (CdmaSignalInfoRec)infoRec.record; + if (sir != null && sir.isPresent && + sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B && + sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED && + sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) { + + Rlog.d(RILJ_LOG_TAG, "Dropping \"" + responseToString(response) + " " + + retToString(response, sir) + "\" to prevent \"ring of death\" bug."); + return; + } + } + + super.notifyRegistrantsCdmaInfoRec(infoRec); + } + + protected class SamsungDriverCall extends DriverCall { + @Override + public String + toString() { + // Samsung CDMA devices' call parcel is formatted differently + // fake unused data for video calls, and fix formatting + // so that voice calls' information can be correctly parsed + return "id=" + index + "," + + state + "," + + "toa=" + TOA + "," + + (isMpty ? "conf" : "norm") + "," + + (isMT ? "mt" : "mo") + "," + + "als=" + als + "," + + (isVoice ? "voc" : "nonvoc") + "," + + "nonvid" + "," + + number + "," + + "cli=" + numberPresentation + "," + + "name=" + name + "," + + namePresentation; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setCurrentPreferredNetworkType() { + if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType IGNORED"); + /* Google added this as a fix for crespo loosing network type after + * taking an OTA. This messes up the data connection state for us + * due to the way we handle network type change (disable data + * then change then re-enable). + */ + } + + @Override + public void setPreferredNetworkType(int networkType , Message response) { + /* Samsung modem implementation does bad things when a datacall is running + * while switching the preferred networktype. + */ + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + if(cm.getMobileDataEnabled()) + { + ConnectivityHandler handler = new ConnectivityHandler(mContext); + handler.setPreferedNetworkType(networkType, response); + } else { + sendPreferredNetworkType(networkType, response); + } + } + + + //Sends the real RIL request to the modem. + private void sendPreferredNetworkType(int networkType, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response); + + rr.mParcel.writeInt(1); + rr.mParcel.writeInt(networkType); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + networkType); + + send(rr); + } + /* private class that does the handling for the dataconnection + * dataconnection is done async, so we send the request for disabling it, + * wait for the response, set the prefered networktype and notify the + * real sender with its result. + */ + private class ConnectivityHandler extends Handler{ + + private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 30; + private Context mContext; + private int mDesiredNetworkType; + //the original message, we need it for calling back the original caller when done + private Message mNetworktypeResponse; + private ConnectivityBroadcastReceiver mConnectivityReceiver = new ConnectivityBroadcastReceiver(); + + public ConnectivityHandler(Context context) + { + mContext = context; + } + + private void startListening() { + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mConnectivityReceiver, filter); + } + + private synchronized void stopListening() { + mContext.unregisterReceiver(mConnectivityReceiver); + } + + public void setPreferedNetworkType(int networkType, Message response) + { + Rlog.d(RILJ_LOG_TAG, "Mobile Dataconnection is online setting it down"); + mDesiredNetworkType = networkType; + mNetworktypeResponse = response; + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + //start listening for the connectivity change broadcast + startListening(); + cm.setMobileDataEnabled(false); + } + + @Override + public void handleMessage(Message msg) { + switch(msg.what) { + //networktype was set, now we can enable the dataconnection again + case MESSAGE_SET_PREFERRED_NETWORK_TYPE: + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + Rlog.d(RILJ_LOG_TAG, "preferred NetworkType set upping Mobile Dataconnection"); + + cm.setMobileDataEnabled(true); + //everything done now call back that we have set the networktype + AsyncResult.forMessage(mNetworktypeResponse, null, null); + mNetworktypeResponse.sendToTarget(); + mNetworktypeResponse = null; + break; + default: + throw new RuntimeException("unexpected event not handled"); + } + } + + private class ConnectivityBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + Rlog.w(RILJ_LOG_TAG, "onReceived() called with " + intent); + return; + } + boolean noConnectivity = + intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + + if (noConnectivity) { + //Ok dataconnection is down, now set the networktype + Rlog.w(RILJ_LOG_TAG, "Mobile Dataconnection is now down setting preferred NetworkType"); + stopListening(); + sendPreferredNetworkType(mDesiredNetworkType, obtainMessage(MESSAGE_SET_PREFERRED_NETWORK_TYPE)); + mDesiredNetworkType = -1; + } + } + } + } +} diff --git a/src/java/com/android/internal/telephony/SamsungExynos3RIL.java b/src/java/com/android/internal/telephony/SamsungExynos3RIL.java new file mode 100644 index 0000000000..698d158ee9 --- /dev/null +++ b/src/java/com/android/internal/telephony/SamsungExynos3RIL.java @@ -0,0 +1,827 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2011, 2012 The CyanogenMod Project + * Copyright (C) 2013 The OmniROM 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 java.util.ArrayList; +import java.util.Collections; +import java.lang.Runtime; +import java.io.IOException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Handler; +import android.os.Message; +import android.os.AsyncResult; +import android.os.Parcel; +import android.os.Registrant; +import android.os.SystemProperties; +import android.telephony.PhoneNumberUtils; +import android.telephony.SignalStrength; +import android.telephony.SmsManager; +import android.telephony.SmsMessage; +import static com.android.internal.telephony.RILConstants.*; + +import com.android.internal.telephony.CallForwardInfo; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.gsm.SuppServiceNotification; +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.uicc.IccCardStatus; +import com.android.internal.telephony.uicc.IccUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.SmsResponse; +import com.android.internal.telephony.cdma.CdmaCallWaitingNotification; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; +import com.android.internal.telephony.cdma.SignalToneUtil; +import com.android.internal.telephony.dataconnection.DataCallResponse; +import com.android.internal.telephony.dataconnection.DcFailCause; + +import android.telephony.Rlog; + +public class SamsungExynos3RIL extends RIL implements CommandsInterface { + + private boolean mSignalbarCount = SystemProperties.getInt("ro.telephony.sends_barcount", 0) == 1 ? true : false; + private boolean mIsSamsungCdma = SystemProperties.getBoolean("ro.ril.samsung_cdma", false); + private Object mCatProCmdBuffer; + + public SamsungExynos3RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + // SAMSUNG SGS STATES + static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007; + static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008; + static final int RIL_UNSOL_GPS_NOTI = 11009; + static final int RIL_UNSOL_AM = 11010; + static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST = 11012; + static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2 = 11011; + static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; + static final int RIL_REQUEST_DIAL_EMERGENCY = 10016; + + static String + requestToString(int request) { + switch (request) { + case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY"; + default: return RIL.requestToString(request); + } + } + + @Override + public void + setRadioPower(boolean on, Message result) { + boolean allow = SystemProperties.getBoolean("persist.ril.enable", true); + if (!allow) { + return; + } + + RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); + + if (on) { + rr.mParcel.writeInt(1); + rr.mParcel.writeInt(1); + } else { + rr.mParcel.writeInt(2); + rr.mParcel.writeInt(0); + rr.mParcel.writeInt(0); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); + } + + @Override + protected Object getOverridenRequestResponse(int mRequest, Parcel p) { + switch(mRequest) { + case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return responseLastCallFailCause(p); + case RIL_REQUEST_VOICE_REGISTRATION_STATE: return responseVoiceRegistrationState(p); + case RIL_REQUEST_CDMA_SUBSCRIPTION: return responseCdmaSubscription(p); + default: return null; + } + } + + @Override + protected boolean hasSamsungSendSmsFix() { return true; } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr; + if (!mIsSamsungCdma && PhoneNumberUtils.isEmergencyNumber(address)) { + dialEmergencyCall(address, clirMode, result); + return; + } + + rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + rr.mParcel.writeString(address); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); // UUS information is absent + + if (uusInfo == null) { + rr.mParcel.writeInt(0); // UUS information is absent + } else { + rr.mParcel.writeInt(1); // UUS information is present + rr.mParcel.writeInt(uusInfo.getType()); + rr.mParcel.writeInt(uusInfo.getDcs()); + rr.mParcel.writeByteArray(uusInfo.getUserData()); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + dialEmergencyCall(String address, int clirMode, Message result) { + RILRequest rr; + Rlog.v(RILJ_LOG_TAG, "Emergency dial: " + address); + + rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result); + rr.mParcel.writeString(address + "/"); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); + rr.mParcel.writeInt(0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + protected void + processUnsolicited (Parcel p) { + int response; + Object ret; + int dataPosition = p.dataPosition(); + + response = p.readInt(); + + switch(response) { + /* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/' + */ + + case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_HSDPA_STATE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break; + + //fixing anoying Exceptions caused by the new Samsung states + //FIXME figure out what the states mean an what data is in the parcel + + case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break; + case RIL_UNSOL_DEVICE_READY_NOTI: ret = responseVoid(p); break; + case RIL_UNSOL_GPS_NOTI: ret = responseVoid(p); break; // Ignored in TW RIL. + case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST: ret = responseVoid(p); break; + case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2: ret = responseVoid(p); break; + case RIL_UNSOL_AM: ret = responseString(p); break; + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_HSDPA_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + boolean newHsdpa = ((int[])ret)[0] == 1; + String curState = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE); + boolean curHsdpa = false; + + if (curState.startsWith("HSDPA")) { + curHsdpa = true; + } else if (!curState.startsWith("UMTS")) { + // Don't send poll request if not on 3g + break; + } + + if (curHsdpa != newHsdpa) { + mVoiceNetworkStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + } + break; + + case RIL_UNSOL_NITZ_TIME_RECEIVED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + String nitz = (String)ret; + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED length = " + + nitz.split("[/:,+-]").length); + + // remove the tailing information that samsung added to the string + if(nitz.split("[/:,+-]").length >= 9) + nitz = nitz.substring(0,(nitz.lastIndexOf(","))); + + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED striped nitz = " + + nitz); + + result[0] = nitz; + result[1] = Long.valueOf(nitzReceiveTime); + + if (mNITZTimeRegistrant != null) { + + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = nitz; + } + break; + + case RIL_UNSOL_SIGNAL_STRENGTH: + // Note this is set to "verbose" because it happens + // frequently + if (RILJ_LOGV) unsljLogvRet(response, ret); + + if (mSignalStrengthRegistrant != null) { + mSignalStrengthRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_PROACTIVE_COMMAND: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatProCmdRegistrant != null) { + mCatProCmdRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } else { + // The RIL will send a CAT proactive command before the + // registrant is registered. Buffer it to make sure it + // does not get ignored (and breaks CatService). + mCatProCmdBuffer = ret; + } + break; + + case RIL_UNSOL_CDMA_INFO_REC: + ArrayList listInfoRecs; + + try { + listInfoRecs = (ArrayList)ret; + } catch (ClassCastException e) { + Rlog.e(RILJ_LOG_TAG, "Unexpected exception casting to listInfoRecs", e); + break; + } + + for (CdmaInformationRecords rec : listInfoRecs) { + if (RILJ_LOGD) unsljLogRet(response, rec); + notifyRegistrantsCdmaInfoRec(rec); + } + break; + + case RIL_UNSOL_AM: + String amString = (String) ret; + Rlog.d(RILJ_LOG_TAG, "Executing AM: " + amString); + + try { + Runtime.getRuntime().exec("am " + amString); + } catch (IOException e) { + e.printStackTrace(); + Rlog.e(RILJ_LOG_TAG, "am " + amString + " could not be executed."); + } + break; + } + } + + @Override + protected Object + responseCallList(Parcel p) { + int num; + boolean isVideo; + ArrayList response; + DriverCall dc; + int dataAvail = p.dataAvail(); + int pos = p.dataPosition(); + int size = p.dataSize(); + + Rlog.d(RILJ_LOG_TAG, "Parcel size = " + size); + Rlog.d(RILJ_LOG_TAG, "Parcel pos = " + pos); + Rlog.d(RILJ_LOG_TAG, "Parcel dataAvail = " + dataAvail); + + num = p.readInt(); + response = new ArrayList(num); + + for (int i = 0 ; i < num ; i++) { + if (mIsSamsungCdma) + dc = new SamsungDriverCall(); + else + dc = new DriverCall(); + + dc.state = DriverCall.stateFromCLCC(p.readInt()); + dc.index = p.readInt(); + dc.TOA = p.readInt(); + dc.isMpty = (0 != p.readInt()); + dc.isMT = (0 != p.readInt()); + dc.als = p.readInt(); + dc.isVoice = (0 != p.readInt()); + isVideo = (0 != p.readInt()); + dc.isVoicePrivacy = (0 != p.readInt()); + dc.number = p.readString(); + int np = p.readInt(); + dc.numberPresentation = DriverCall.presentationFromCLIP(np); + dc.name = p.readString(); + dc.namePresentation = p.readInt(); + int uusInfoPresent = p.readInt(); + + Rlog.d(RILJ_LOG_TAG, "state = " + dc.state); + Rlog.d(RILJ_LOG_TAG, "index = " + dc.index); + Rlog.d(RILJ_LOG_TAG, "state = " + dc.TOA); + Rlog.d(RILJ_LOG_TAG, "isMpty = " + dc.isMpty); + Rlog.d(RILJ_LOG_TAG, "isMT = " + dc.isMT); + Rlog.d(RILJ_LOG_TAG, "als = " + dc.als); + Rlog.d(RILJ_LOG_TAG, "isVoice = " + dc.isVoice); + Rlog.d(RILJ_LOG_TAG, "isVideo = " + isVideo); + Rlog.d(RILJ_LOG_TAG, "number = " + dc.number); + Rlog.d(RILJ_LOG_TAG, "numberPresentation = " + np); + Rlog.d(RILJ_LOG_TAG, "name = " + dc.name); + Rlog.d(RILJ_LOG_TAG, "namePresentation = " + dc.namePresentation); + Rlog.d(RILJ_LOG_TAG, "uusInfoPresent = " + uusInfoPresent); + + if (uusInfoPresent == 1) { + dc.uusInfo = new UUSInfo(); + dc.uusInfo.setType(p.readInt()); + dc.uusInfo.setDcs(p.readInt()); + byte[] userData = p.createByteArray(); + dc.uusInfo.setUserData(userData); + Rlog + .v(RILJ_LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + Rlog.v(RILJ_LOG_TAG, "Incoming UUS : NOT present!"); + } + + // Make sure there's a leading + on addresses with a TOA of 145 + dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA); + + response.add(dc); + + if (dc.isVoicePrivacy) { + mVoicePrivacyOnRegistrants.notifyRegistrants(); + Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is enabled"); + } else { + mVoicePrivacyOffRegistrants.notifyRegistrants(); + Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is disabled"); + } + } + + Collections.sort(response); + + return response; + } + + protected Object + responseLastCallFailCause(Parcel p) { + int response[] = (int[])responseInts(p); + + if (mIsSamsungCdma && response.length > 0 && + response[0] == com.android.internal.telephony.cdma.CallFailCause.ERROR_UNSPECIFIED) { + + // Far-end hangup returns ERROR_UNSPECIFIED, which shows "Call Lost" dialog. + Rlog.d(RILJ_LOG_TAG, "Overriding ERROR_UNSPECIFIED fail cause with NORMAL_CLEARING."); + response[0] = com.android.internal.telephony.cdma.CallFailCause.NORMAL_CLEARING; + } + + return response; + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + // When SIM is PIN-unlocked, the RIL responds with APPSTATE_UNKNOWN and + // does not follow up with RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED. We + // notify the system here. + String state = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE); + if (!"READY".equals(state) && mIccStatusChangedRegistrants != null && !mIsSamsungCdma) { + mIccStatusChangedRegistrants.notifyRegistrants(); + } + + int[] response = new int[7]; + for (int i = 0 ; i < 7 ; i++) { + response[i] = p.readInt(); + } + + if (mIsSamsungCdma){ + if(response[3] < 0){ + response[3] = -response[3]; + } + // Framework takes care of the rest for us. + } + else { + /* Matching Samsung signal strength to asu. + Method taken from Samsungs cdma/gsmSignalStateTracker */ + if(mSignalbarCount) + { + // Samsung sends the count of bars that should be displayed instead of + // a real signal strength + response[0] = ((response[0] & 0xFF00) >> 8) * 3; // gsmDbm + } else { + response[0] = response[0] & 0xFF; // gsmDbm + } + response[1] = -1; // gsmEcio + response[2] = (response[2] < 0)?-120:-response[2]; // cdmaDbm + response[3] = (response[3] < 0)?-160:-response[3]; // cdmaEcio + response[4] = (response[4] < 0)?-120:-response[4]; // evdoRssi + response[5] = (response[5] < 0)?-1:-response[5]; // evdoEcio + if(response[6] < 0 || response[6] > 8) + response[6] = -1; + } + + SignalStrength signalStrength = new SignalStrength( + response[0], response[1], response[2], response[3], response[4], + response[5], response[6], !mIsSamsungCdma); + return signalStrength; + } + + protected Object + responseVoiceRegistrationState(Parcel p) { + String response[] = (String[])responseStrings(p); + + if (mIsSamsungCdma && response.length > 6) { + // These values are provided in hex, convert to dec. + response[4] = Integer.toString(Integer.parseInt(response[4], 16)); // baseStationId + response[5] = Integer.toString(Integer.parseInt(response[5], 16)); // baseStationLatitude + response[6] = Integer.toString(Integer.parseInt(response[6], 16)); // baseStationLongitude + } + + return response; + } + + @Override + protected Object + responseGetPreferredNetworkType(Parcel p) { + int response[] = (int[]) responseInts(p); + + // When the modem responds Phone.NT_MODE_GLOBAL, it means Phone.NT_MODE_WCDMA_PREF + if (!mIsSamsungCdma && response[0] == Phone.NT_MODE_GLOBAL) { + Rlog.d(RILJ_LOG_TAG, "Overriding network type response from global to WCDMA preferred"); + response[0] = Phone.NT_MODE_WCDMA_PREF; + } + + return response; + } + + @Override + protected Object + responseSetupDataCall(Parcel p) { + DataCallResponse dataCall = new DataCallResponse(); + String strings[] = (String []) responseStrings(p); + + if (strings.length >= 2) { + dataCall.cid = Integer.parseInt(strings[0]); + + if (mIsSamsungCdma) { + // We're responsible for starting/stopping the pppd_cdma service. + if (!startPppdCdmaService(strings[1])) { + // pppd_cdma service didn't respond timely. + dataCall.status = DcFailCause.ERROR_UNSPECIFIED.getErrorCode(); + return dataCall; + } + + // pppd_cdma service responded, pull network parameters set by ip-up script. + dataCall.ifname = SystemProperties.get("net.cdma.ppp.interface"); + String ifprop = "net." + dataCall.ifname; + + dataCall.addresses = new String[] {SystemProperties.get(ifprop + ".local-ip")}; + dataCall.gateways = new String[] {SystemProperties.get(ifprop + ".remote-ip")}; + dataCall.dnses = new String[] {SystemProperties.get(ifprop + ".dns1"), + SystemProperties.get(ifprop + ".dns2")}; + } else { + dataCall.ifname = strings[1]; + + if (strings.length >= 3) { + dataCall.addresses = strings[2].split(" "); + } + } + } else { + if (mIsSamsungCdma) { + // On rare occasion the pppd_cdma service is left active from a stale + // session, causing the data call setup to fail. Make sure that pppd_cdma + // is stopped now, so that the next setup attempt may succeed. + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=0 to make sure pppd_cdma is stopped."); + SystemProperties.set("ril.cdma.data_state", "0"); + } + + dataCall.status = DcFailCause.ERROR_UNSPECIFIED.getErrorCode(); // Who knows? + } + + return dataCall; + } + + private boolean startPppdCdmaService(String ttyname) { + SystemProperties.set("net.cdma.datalinkinterface", ttyname); + + // Connecting: Set ril.cdma.data_state=1 to (re)start pppd_cdma service, + // which responds by setting ril.cdma.data_state=2 once connection is up. + SystemProperties.set("ril.cdma.data_state", "1"); + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=1, waiting for ril.cdma.data_state=2."); + + // Typically takes < 200 ms on my Epic, so sleep in 100 ms intervals. + for (int i = 0; i < 10; i++) { + try {Thread.sleep(100);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Rlog.d(RILJ_LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Taking > 1 s here, try up to 10 s, which is hopefully long enough. + for (int i = 1; i < 10; i++) { + try {Thread.sleep(1000);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Rlog.d(RILJ_LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Rlog.d(RILJ_LOG_TAG, "Didn't get ril.cdma.data_state=2 timely, aborting."); + SystemProperties.set("ril.cdma.data_state", "0"); + + return false; + } + + @Override + public void + deactivateDataCall(int cid, int reason, Message result) { + if (mIsSamsungCdma) { + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Rlog.d(RILJ_LOG_TAG, "Set ril.cdma.data_state=0."); + SystemProperties.set("ril.cdma.data_state", "0"); + } + + super.deactivateDataCall(cid, reason, result); + } + + protected Object + responseCdmaSubscription(Parcel p) { + String response[] = (String[])responseStrings(p); + + if (/* mIsSamsungCdma && */ response.length == 4) { + // PRL version is missing in subscription parcel, add it from properties. + String prlVersion = SystemProperties.get("ril.prl_ver_1").split(":")[1]; + response = new String[] {response[0], response[1], response[2], + response[3], prlVersion}; + } + + return response; + } + + // Workaround for Samsung CDMA "ring of death" bug: + // + // Symptom: As soon as the phone receives notice of an incoming call, an + // audible "old fashioned ring" is emitted through the earpiece and + // persists through the duration of the call, or until reboot if the call + // isn't answered. + // + // Background: The CDMA telephony stack implements a number of "signal info + // tones" that are locally generated by ToneGenerator and mixed into the + // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests. + // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the + // radio just prior to notice of an incoming call when the voice call + // path is muted. CallNotifier is responsible for stopping all signal + // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a + // "new ringing connection", prior to unmuting the voice call path. + // + // Problem: CallNotifier's incoming call path is designed to minimize + // latency to notify users of incoming calls ASAP. Thus, + // SignalInfoTonePlayer requests are handled asynchronously by spawning a + // one-shot thread for each. Unfortunately the ToneGenerator API does + // not provide a mechanism to specify an ordering on requests, and thus, + // unexpected thread interleaving may result in ToneGenerator processing + // them in the opposite order that CallNotifier intended. In this case, + // playing the "signal off" tone first, followed by playing the "old + // fashioned ring" indefinitely. + // + // Solution: An API change to ToneGenerator is required to enable + // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any + // request that's older than the most recent observed). Such a change, + // or another appropriate fix should be implemented in AOSP first. + // + // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio, + // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and + // drop it so it's never seen by CallNotifier. If other signal tones are + // observed to cause this problem, they should be dropped here as well. + @Override + protected void + notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { + final int response = RIL_UNSOL_CDMA_INFO_REC; + + if (/* mIsSamsungCdma && */ infoRec.record instanceof CdmaSignalInfoRec) { + CdmaSignalInfoRec sir = (CdmaSignalInfoRec)infoRec.record; + if (sir != null && sir.isPresent && + sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B && + sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED && + sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) { + + Rlog.d(RILJ_LOG_TAG, "Dropping \"" + responseToString(response) + " " + + retToString(response, sir) + "\" to prevent \"ring of death\" bug."); + return; + } + } + + super.notifyRegistrantsCdmaInfoRec(infoRec); + } + + protected class SamsungDriverCall extends DriverCall { + @Override + public String + toString() { + // Samsung CDMA devices' call parcel is formatted differently + // fake unused data for video calls, and fix formatting + // so that voice calls' information can be correctly parsed + return "id=" + index + "," + + state + "," + + "toa=" + TOA + "," + + (isMpty ? "conf" : "norm") + "," + + (isMT ? "mt" : "mo") + "," + + "als=" + als + "," + + (isVoice ? "voc" : "nonvoc") + "," + + "nonvid" + "," + + number + "," + + "cli=" + numberPresentation + "," + + "name=" + name + "," + + namePresentation; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setCurrentPreferredNetworkType() { + if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType IGNORED"); + /* Google added this as a fix for crespo loosing network type after + * taking an OTA. This messes up the data connection state for us + * due to the way we handle network type change (disable data + * then change then re-enable). + */ + } + + @Override + public void setPreferredNetworkType(int networkType , Message response) { + /* Samsung modem implementation does bad things when a datacall is running + * while switching the preferred networktype. + */ + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo.State mobileState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState(); + if (mobileState == NetworkInfo.State.CONNECTED || mobileState == NetworkInfo.State.CONNECTING) { + ConnectivityHandler handler = new ConnectivityHandler(mContext); + handler.setPreferedNetworkType(networkType, response); + } else { + sendPreferedNetworktype(networkType, response); + } + } + + + //Sends the real RIL request to the modem. + private void sendPreferedNetworktype(int networkType, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response); + + rr.mParcel.writeInt(1); + rr.mParcel.writeInt(networkType); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + networkType); + + send(rr); + } + + @Override + public void setOnCatProactiveCmd(Handler h, int what, Object obj) { + mCatProCmdRegistrant = new Registrant (h, what, obj); + if (mCatProCmdBuffer != null) { + mCatProCmdRegistrant.notifyRegistrant( + new AsyncResult (null, mCatProCmdBuffer, null)); + mCatProCmdBuffer = null; + } + } + + /* private class that does the handling for the dataconnection + * dataconnection is done async, so we send the request for disabling it, + * wait for the response, set the prefered networktype and notify the + * real sender with its result. + */ + private class ConnectivityHandler extends Handler{ + + private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 30; + private Context mContext; + private int mDesiredNetworkType; + //the original message, we need it for calling back the original caller when done + private Message mNetworktypeResponse; + private ConnectivityBroadcastReceiver mConnectivityReceiver = new ConnectivityBroadcastReceiver(); + + public ConnectivityHandler(Context context) + { + mContext = context; + } + + private void startListening() { + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mConnectivityReceiver, filter); + } + + private synchronized void stopListening() { + mContext.unregisterReceiver(mConnectivityReceiver); + } + + public void setPreferedNetworkType(int networkType, Message response) + { + Rlog.d(RILJ_LOG_TAG, "Mobile Dataconnection is online setting it down"); + mDesiredNetworkType = networkType; + mNetworktypeResponse = response; + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + //start listening for the connectivity change broadcast + startListening(); + cm.setMobileDataEnabled(false); + } + + @Override + public void handleMessage(Message msg) { + switch(msg.what) { + //networktype was set, now we can enable the dataconnection again + case MESSAGE_SET_PREFERRED_NETWORK_TYPE: + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + Rlog.d(RILJ_LOG_TAG, "preferred NetworkType set upping Mobile Dataconnection"); + + cm.setMobileDataEnabled(true); + //everything done now call back that we have set the networktype + AsyncResult.forMessage(mNetworktypeResponse, null, null); + mNetworktypeResponse.sendToTarget(); + mNetworktypeResponse = null; + break; + default: + throw new RuntimeException("unexpected event not handled"); + } + } + + private class ConnectivityBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + Rlog.w(RILJ_LOG_TAG, "onReceived() called with " + intent); + return; + } + boolean noConnectivity = + intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + + if (noConnectivity) { + //Ok dataconnection is down, now set the networktype + Rlog.w(RILJ_LOG_TAG, "Mobile Dataconnection is now down setting preferred NetworkType"); + stopListening(); + sendPreferedNetworktype(mDesiredNetworkType, obtainMessage(MESSAGE_SET_PREFERRED_NETWORK_TYPE)); + mDesiredNetworkType = -1; + } + } + } + } +} diff --git a/src/java/com/android/internal/telephony/SamsungExynos4RIL.java b/src/java/com/android/internal/telephony/SamsungExynos4RIL.java new file mode 100644 index 0000000000..d4c809a9d1 --- /dev/null +++ b/src/java/com/android/internal/telephony/SamsungExynos4RIL.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2011 The CyanogenMod 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 static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.os.AsyncResult; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Parcel; +import android.text.TextUtils; +import android.telephony.Rlog; + +import android.telephony.PhoneNumberUtils; + +import java.util.ArrayList; + +public class SamsungExynos4RIL extends RIL implements CommandsInterface { + + //SAMSUNG STATES + static final int RIL_REQUEST_GET_CELL_BROADCAST_CONFIG = 10002; + + static final int RIL_REQUEST_SEND_ENCODED_USSD = 10005; + static final int RIL_REQUEST_SET_PDA_MEMORY_STATUS = 10006; + static final int RIL_REQUEST_GET_PHONEBOOK_STORAGE_INFO = 10007; + static final int RIL_REQUEST_GET_PHONEBOOK_ENTRY = 10008; + static final int RIL_REQUEST_ACCESS_PHONEBOOK_ENTRY = 10009; + static final int RIL_REQUEST_DIAL_VIDEO_CALL = 10010; + static final int RIL_REQUEST_CALL_DEFLECTION = 10011; + static final int RIL_REQUEST_READ_SMS_FROM_SIM = 10012; + static final int RIL_REQUEST_USIM_PB_CAPA = 10013; + static final int RIL_REQUEST_LOCK_INFO = 10014; + + static final int RIL_REQUEST_DIAL_EMERGENCY = 10016; + static final int RIL_REQUEST_GET_STOREAD_MSG_COUNT = 10017; + static final int RIL_REQUEST_STK_SIM_INIT_EVENT = 10018; + static final int RIL_REQUEST_GET_LINE_ID = 10019; + static final int RIL_REQUEST_SET_LINE_ID = 10020; + static final int RIL_REQUEST_GET_SERIAL_NUMBER = 10021; + static final int RIL_REQUEST_GET_MANUFACTURE_DATE_NUMBER = 10022; + static final int RIL_REQUEST_GET_BARCODE_NUMBER = 10023; + static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_BOOTSTRAP = 10024; + static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_NAF = 10025; + static final int RIL_REQUEST_SIM_TRANSMIT_BASIC = 10026; + static final int RIL_REQUEST_SIM_OPEN_CHANNEL = 10027; + static final int RIL_REQUEST_SIM_CLOSE_CHANNEL = 10028; + static final int RIL_REQUEST_SIM_TRANSMIT_CHANNEL = 10029; + static final int RIL_REQUEST_SIM_AUTH = 10030; + static final int RIL_REQUEST_PS_ATTACH = 10031; + static final int RIL_REQUEST_PS_DETACH = 10032; + static final int RIL_REQUEST_ACTIVATE_DATA_CALL = 10033; + static final int RIL_REQUEST_CHANGE_SIM_PERSO = 10034; + static final int RIL_REQUEST_ENTER_SIM_PERSO = 10035; + static final int RIL_REQUEST_GET_TIME_INFO = 10036; + static final int RIL_REQUEST_OMADM_SETUP_SESSION = 10037; + static final int RIL_REQUEST_OMADM_SERVER_START_SESSION = 10038; + static final int RIL_REQUEST_OMADM_CLIENT_START_SESSION = 10039; + static final int RIL_REQUEST_OMADM_SEND_DATA = 10040; + static final int RIL_REQUEST_CDMA_GET_DATAPROFILE = 10041; + static final int RIL_REQUEST_CDMA_SET_DATAPROFILE = 10042; + static final int RIL_REQUEST_CDMA_GET_SYSTEMPROPERTIES = 10043; + static final int RIL_REQUEST_CDMA_SET_SYSTEMPROPERTIES = 10044; + static final int RIL_REQUEST_SEND_SMS_COUNT = 10045; + static final int RIL_REQUEST_SEND_SMS_MSG = 10046; + static final int RIL_REQUEST_SEND_SMS_MSG_READ_STATUS = 10047; + static final int RIL_REQUEST_MODEM_HANGUP = 10048; + static final int RIL_REQUEST_SET_SIM_POWER = 10049; + static final int RIL_REQUEST_SET_PREFERRED_NETWORK_LIST = 10050; + static final int RIL_REQUEST_GET_PREFERRED_NETWORK_LIST = 10051; + static final int RIL_REQUEST_HANGUP_VT = 10052; + + static final int RIL_UNSOL_RELEASE_COMPLETE_MESSAGE = 11001; + static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; + static final int RIL_UNSOL_STK_CALL_CONTROL_RESULT = 11003; + static final int RIL_UNSOL_DUN_CALL_STATUS = 11004; + + static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007; + static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008; + static final int RIL_UNSOL_GPS_NOTI = 11009; + static final int RIL_UNSOL_AM = 11010; + static final int RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL = 11011; + static final int RIL_UNSOL_DATA_SUSPEND_RESUME = 11012; + static final int RIL_UNSOL_SAP = 11013; + + static final int RIL_UNSOL_SIM_SMS_STORAGE_AVAILALE = 11015; + static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; + static final int RIL_UNSOL_WB_AMR_STATE = 11017; + static final int RIL_UNSOL_TWO_MIC_STATE = 11018; + static final int RIL_UNSOL_DHA_STATE = 11019; + static final int RIL_UNSOL_UART = 11020; + static final int RIL_UNSOL_RESPONSE_HANDOVER = 11021; + static final int RIL_UNSOL_IPV6_ADDR = 11022; + static final int RIL_UNSOL_NWK_INIT_DISC_REQUEST = 11023; + static final int RIL_UNSOL_RTS_INDICATION = 11024; + static final int RIL_UNSOL_OMADM_SEND_DATA = 11025; + static final int RIL_UNSOL_DUN = 11026; + static final int RIL_UNSOL_SYSTEM_REBOOT = 11027; + static final int RIL_UNSOL_VOICE_PRIVACY_CHANGED = 11028; + static final int RIL_UNSOL_UTS_GETSMSCOUNT = 11029; + static final int RIL_UNSOL_UTS_GETSMSMSG = 11030; + static final int RIL_UNSOL_UTS_GET_UNREAD_SMS_STATUS = 11031; + static final int RIL_UNSOL_MIP_CONNECT_STATUS = 11032; + + public SamsungExynos4RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + static String + requestToString(int request) { + switch (request) { + case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY"; + default: return RIL.requestToString(request); + } + } + + @Override + protected Object getOverridenRequestResponse(int mRequest, Parcel p) { + switch(mRequest) { + case RIL_REQUEST_DIAL_EMERGENCY: return responseVoid(p); + default: return null; + } + } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr; + if (PhoneNumberUtils.isEmergencyNumber(address)) { + dialEmergencyCall(address, clirMode, result); + return; + } + + rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + rr.mParcel.writeString(address); + rr.mParcel.writeInt(clirMode); + + if (uusInfo == null) { + rr.mParcel.writeInt(0); // UUS information is absent + } else { + rr.mParcel.writeInt(1); // UUS information is present + rr.mParcel.writeInt(uusInfo.getType()); + rr.mParcel.writeInt(uusInfo.getDcs()); + rr.mParcel.writeByteArray(uusInfo.getUserData()); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + dialEmergencyCall(String address, int clirMode, Message result) { + RILRequest rr; + Rlog.v(RILJ_LOG_TAG, "Emergency dial: " + address); + + rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result); + rr.mParcel.writeString(address + "/"); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); // UUS information is absent + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } +} diff --git a/src/java/com/android/internal/telephony/SamsungQualcommRIL.java b/src/java/com/android/internal/telephony/SamsungQualcommRIL.java new file mode 100644 index 0000000000..5b87f5b56d --- /dev/null +++ b/src/java/com/android/internal/telephony/SamsungQualcommRIL.java @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2012-2013 The CyanogenMod Project + * Copyright (C) 2013 The OmniROM 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 static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.media.AudioManager; +import android.os.AsyncResult; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Parcel; +import android.telephony.SmsMessage; +import android.os.SystemProperties; +import android.os.SystemClock; +import android.provider.Settings; +import android.text.TextUtils; +import android.telephony.Rlog; + +import android.telephony.SignalStrength; + +import android.telephony.PhoneNumberUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; +import com.android.internal.telephony.cdma.SignalToneUtil; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; + +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.uicc.IccCardStatus; + +/** + * Qualcomm RIL for the Samsung family. + * Quad core Exynos4 with Qualcomm modem and later is supported + * Snapdragon S3 and later is supported + * This RIL is univerisal meaning it supports CDMA and GSM radio. + * Handles most GSM and CDMA cases. + * {@hide} + */ +public class SamsungQualcommRIL extends QualcommMSIM42RIL implements CommandsInterface { + + private AudioManager mAudioManager; + + private Object mSMSLock = new Object(); + private boolean mIsSendingSMS = false; + private boolean isGSM = false; + private boolean passedCheck=true; + public static final long SEND_SMS_TIMEOUT_IN_MS = 30000; + private String homeOperator= SystemProperties.get("ro.cdma.home.operator.numeric"); + private String operator= SystemProperties.get("ro.cdma.home.operator.alpha"); + private boolean oldRilState = needsOldRilFeature("exynos4RadioState"); + private boolean googleEditionSS = needsOldRilFeature("googleEditionSS"); + private boolean driverCall = needsOldRilFeature("newDriverCall"); + private String[] lastKnownOfGood = {null, null, null}; + public SamsungQualcommRIL(Context context, int networkMode, + int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); + } + + @Override + protected Object + responseIccCardStatus(Parcel p) { + IccCardApplicationStatus appStatus; + + IccCardStatus cardStatus = new IccCardStatus(); + cardStatus.setCardState(p.readInt()); + cardStatus.setUniversalPinState(p.readInt()); + cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt(); + cardStatus.mCdmaSubscriptionAppIndex = p.readInt(); + cardStatus.mImsSubscriptionAppIndex = p.readInt(); + + int numApplications = p.readInt(); + + // limit to maximum allowed applications + if (numApplications > IccCardStatus.CARD_MAX_APPS) { + numApplications = IccCardStatus.CARD_MAX_APPS; + } + cardStatus.mApplications = new IccCardApplicationStatus[numApplications]; + if (numApplications==1 && !isGSM){ + cardStatus.mApplications = new IccCardApplicationStatus[numApplications+2]; + } + + appStatus = new IccCardApplicationStatus(); + for (int i = 0 ; i < numApplications ; i++) { + appStatus = new IccCardApplicationStatus(); + appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt()); + appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt()); + appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt()); + appStatus.aid = p.readString(); + appStatus.app_label = p.readString(); + appStatus.pin1_replaced = p.readInt(); + appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt()); + appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt()); + p.readInt(); // remaining_count_pin1 - pin1_num_retries + p.readInt(); // remaining_count_puk1 - puk1_num_retries + p.readInt(); // remaining_count_pin2 - pin2_num_retries + p.readInt(); // remaining_count_puk2 - puk2_num_retries + p.readInt(); // - perso_unblock_retries + cardStatus.mApplications[i] = appStatus; + } + if (numApplications==1 && !isGSM) { + cardStatus.mCdmaSubscriptionAppIndex = 1; + cardStatus.mImsSubscriptionAppIndex = 2; + IccCardApplicationStatus appStatus2 = new IccCardApplicationStatus(); + appStatus2.app_type = appStatus2.AppTypeFromRILInt(4); // csim state + appStatus2.app_state = appStatus.app_state; + appStatus2.perso_substate = appStatus.perso_substate; + appStatus2.aid = appStatus.aid; + appStatus2.app_label = appStatus.app_label; + appStatus2.pin1_replaced = appStatus.pin1_replaced; + appStatus2.pin1 = appStatus.pin1; + appStatus2.pin2 = appStatus.pin2; + cardStatus.mApplications[cardStatus.mCdmaSubscriptionAppIndex] = appStatus2; + IccCardApplicationStatus appStatus3 = new IccCardApplicationStatus(); + appStatus3.app_type = appStatus3.AppTypeFromRILInt(5); // ims state + appStatus3.app_state = appStatus.app_state; + appStatus3.perso_substate = appStatus.perso_substate; + appStatus3.aid = appStatus.aid; + appStatus3.app_label = appStatus.app_label; + appStatus3.pin1_replaced = appStatus.pin1_replaced; + appStatus3.pin1 = appStatus.pin1; + appStatus3.pin2 = appStatus.pin2; + cardStatus.mApplications[cardStatus.mImsSubscriptionAppIndex] = appStatus3; + } + return cardStatus; + } + + @Override + public void + sendCdmaSms(byte[] pdu, Message result) { + smsLock(); + super.sendCdmaSms(pdu, result); + } + + @Override + public void + sendSMS (String smscPDU, String pdu, Message result) { + smsLock(); + super.sendSMS(smscPDU, pdu, result); + } + + private void smsLock(){ + // Do not send a new SMS until the response for the previous SMS has been received + // * for the error case where the response never comes back, time out after + // 30 seconds and just try the next SEND_SMS + synchronized (mSMSLock) { + long timeoutTime = SystemClock.elapsedRealtime() + SEND_SMS_TIMEOUT_IN_MS; + long waitTimeLeft = SEND_SMS_TIMEOUT_IN_MS; + while (mIsSendingSMS && (waitTimeLeft > 0)) { + Rlog.d(RILJ_LOG_TAG, "sendSMS() waiting for response of previous SEND_SMS"); + try { + mSMSLock.wait(waitTimeLeft); + } catch (InterruptedException ex) { + // ignore the interrupt and rewait for the remainder + } + waitTimeLeft = timeoutTime - SystemClock.elapsedRealtime(); + } + if (waitTimeLeft <= 0) { + Rlog.e(RILJ_LOG_TAG, "sendSms() timed out waiting for response of previous CDMA_SEND_SMS"); + } + mIsSendingSMS = true; + } + + } + + @Override + protected Object responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + // This is a mashup of algorithms used in + // SamsungQualcommUiccRIL.java + + // Get raw data + response = new int[numInts]; + for (int i = 0; i < numInts; i++) { + response[i] = p.readInt(); + } + //gsm + response[0] &= 0xff; //gsmDbm + + //cdma + // Take just the least significant byte as the signal strength + response[2] %= 256; + response[4] %= 256; + + // RIL_LTE_SignalStrength + if (googleEditionSS && !isGSM){ + response[8] = response[2]; + }else if (response[7] == 99) { + // If LTE is not enabled, clear LTE results + // 7-11 must be -1 for GSM signal strength to be used (see + // frameworks/base/telephony/java/android/telephony/SignalStrength.java) + response[8] = SignalStrength.INVALID; + response[9] = SignalStrength.INVALID; + response[10] = SignalStrength.INVALID; + response[11] = SignalStrength.INVALID; + }else{ // lte is gsm on samsung/qualcomm cdma stack + response[7] &= 0xff; + } + return new SignalStrength(response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7], response[8], response[9], response[10], response[11], (p.readInt() != 0)); + + } + + @Override + protected RadioState getRadioStateFromInt(int stateInt) { + if(!oldRilState) + super.getRadioStateFromInt(stateInt); + RadioState state; + + /* RIL_RadioState ril.h */ + switch(stateInt) { + case 0: state = RadioState.RADIO_OFF; break; + case 1: + case 2: state = RadioState.RADIO_UNAVAILABLE; break; + case 4: + // When SIM is PIN-unlocked, RIL doesn't respond with RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED. + // We notify the system here. + Rlog.d(RILJ_LOG_TAG, "SIM is PIN-unlocked now"); + if (mIccStatusChangedRegistrants != null) { + mIccStatusChangedRegistrants.notifyRegistrants(); + } + case 3: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 13: state = RadioState.RADIO_ON; break; + + default: + throw new RuntimeException( + "Unrecognized RIL_RadioState: " + stateInt); + } + return state; + } + + @Override + public void setPhoneType(int phoneType){ + super.setPhoneType(phoneType); + isGSM = (phoneType != RILConstants.CDMA_PHONE); + } + + @Override + protected Object + responseCallList(Parcel p) { + samsungDriverCall = (driverCall && !isGSM) || mRilVersion < 7 ? false : true; + if(driverCall && passedCheck) + mAudioManager.setParameters("wide_voice_enable=false"); + return super.responseCallList(p); + } + + @Override + protected void + processUnsolicited (Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + switch(response) { + case RIL_UNSOL_RIL_CONNECTED: // Fix for NV/RUIM setting on CDMA SIM devices + // skip getcdmascriptionsource as if qualcomm handles it in the ril binary + ret = responseInts(p); + setRadioPower(false, null); + setPreferredNetworkType(mPreferredNetworkType, null); + int cdmaSubscription = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.CDMA_SUBSCRIPTION_MODE, -1); + if(cdmaSubscription != -1) { + setCdmaSubscriptionSource(mCdmaSubscription, null); + } + setCellInfoListRate(Integer.MAX_VALUE, null); + notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); + break; + case RIL_UNSOL_NITZ_TIME_RECEIVED: + handleNitzTimeReceived(p); + break; + // SAMSUNG STATES + case SamsungExynos4RIL.RIL_UNSOL_AM: + ret = responseString(p); + String amString = (String) ret; + Rlog.d(RILJ_LOG_TAG, "Executing AM: " + amString); + + try { + Runtime.getRuntime().exec("am " + amString); + } catch (IOException e) { + e.printStackTrace(); + Rlog.e(RILJ_LOG_TAG, "am " + amString + " could not be executed."); + } + break; + case SamsungExynos4RIL.RIL_UNSOL_RESPONSE_HANDOVER: + ret = responseVoid(p); + break; + case 1036: + ret = responseVoid(p); + break; + case SamsungExynos4RIL.RIL_UNSOL_WB_AMR_STATE: + ret = responseInts(p); + setWbAmr(((int[])ret)[0]); + break; + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + } + + @Override + protected Object getOverridenRequestResponse(int mRequest, Parcel p) { + switch(mRequest) { + // prevent exceptions from happenimg because the null value is null or a hexadecimel. so convert if it is not null + case RIL_REQUEST_VOICE_REGISTRATION_STATE: return responseVoiceDataRegistrationState(p); + case RIL_REQUEST_DATA_REGISTRATION_STATE: return responseVoiceDataRegistrationState(p); + // this fixes bogus values the modem creates + // sometimes the ril may print out + // (always on sprint) + // sprint: (empty,empty,31000) + // this problemaic on sprint, lte won't start, response is slow + //speeds up response time on eherpderpd/lte networks + case RIL_REQUEST_OPERATOR: return operatorCheck(p); + default: return null; + } + } + + // CDMA FIXES, this fixes bogus values in nv/sim on d2/jf/t0 cdma family or bogus information from sim card + private Object + operatorCheck(Parcel p) { + String response[] = (String[])responseStrings(p); + for(int i=0; i<3; i++){ + if (response[i]!= null){ + if (i<2){ + if (response[i].equals(" Empty") || (response[i].equals("") && !isGSM)) { + response[i]=operator; + } else if (!response[i].equals("")) { + try { + Integer.parseInt(response[i]); + response[i]=Operators.operatorReplace(response[i]); + //optimize + if(i==0) + response[i+1]=response[i]; + } catch(NumberFormatException E){ + // do nothing + } + } + } else if (response[i].equals("31000")|| response[i].equals("11111") || response[i].equals("123456") || response[i].equals("31099") || (response[i].equals("") && !isGSM)){ + response[i]=homeOperator; + } + lastKnownOfGood[i]=response[i]; + }else{ + if(lastKnownOfGood[i]!=null) + response[i]=lastKnownOfGood[i]; + } + } + return response; + } + // handle exceptions + private Object + responseVoiceDataRegistrationState(Parcel p) { + String response[] = (String[])responseStrings(p); + if (isGSM){ + return response; + } + if ( response.length>=10){ + for(int i=6; i<=9; i++){ + if (response[i]== null){ + response[i]=Integer.toString(Integer.MAX_VALUE); + } else { + try { + Integer.parseInt(response[i]); + } catch(NumberFormatException e) { + response[i]=Integer.toString(Integer.parseInt(response[i],16)); + } + } + } + } + + return response; + } + // has no effect + // for debugging purposes , just generate out anything from response + public static String s(String a[]){ + StringBuffer result = new StringBuffer(); + + for (int i = 0; i < a.length; i++) { + result.append( a[i] ); + result.append(","); + } + return result.toString(); + } + // end of cdma fix + + /** + * Set audio parameter "wb_amr" for HD-Voice (Wideband AMR). + * + * @param state: 0 = unsupported, 1 = supported. + * REQUIRED FOR JF FAMILY THIS SETS THE INFORMATION + * CRASHES WITHOUT THIS FUNCTION + * part of the new csd binary + */ + private void setWbAmr(int state) { + if (state == 1) { + Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=on"); + mAudioManager.setParameters("wide_voice_enable=true"); + }else if (state == 0) { + Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=on"); + mAudioManager.setParameters("wide_voice_enable=false"); + } + //prevent race conditions when the two meeets + if (passedCheck) + passedCheck=false; + } + + // Workaround for Samsung CDMA "ring of death" bug: + // + // Symptom: As soon as the phone receives notice of an incoming call, an + // audible "old fashioned ring" is emitted through the earpiece and + // persists through the duration of the call, or until reboot if the call + // isn't answered. + // + // Background: The CDMA telephony stack implements a number of "signal info + // tones" that are locally generated by ToneGenerator and mixed into the + // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests. + // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the + // radio just prior to notice of an incoming call when the voice call + // path is muted. CallNotifier is responsible for stopping all signal + // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a + // "new ringing connection", prior to unmuting the voice call path. + // + // Problem: CallNotifier's incoming call path is designed to minimize + // latency to notify users of incoming calls ASAP. Thus, + // SignalInfoTonePlayer requests are handled asynchronously by spawning a + // one-shot thread for each. Unfortunately the ToneGenerator API does + // not provide a mechanism to specify an ordering on requests, and thus, + // unexpected thread interleaving may result in ToneGenerator processing + // them in the opposite order that CallNotifier intended. In this case, + // playing the "signal off" tone first, followed by playing the "old + // fashioned ring" indefinitely. + // + // Solution: An API change to ToneGenerator is required to enable + // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any + // request that's older than the most recent observed). Such a change, + // or another appropriate fix should be implemented in AOSP first. + // + // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio, + // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and + // drop it so it's never seen by CallNotifier. If other signal tones are + // observed to cause this problem, they should be dropped here as well. + @Override + protected void notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { + final int response = RIL_UNSOL_CDMA_INFO_REC; + + if (infoRec.record instanceof CdmaSignalInfoRec) { + CdmaSignalInfoRec sir = (CdmaSignalInfoRec) infoRec.record; + if (sir != null + && sir.isPresent + && sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B + && sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED + && sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) { + + Rlog.d(RILJ_LOG_TAG, "Dropping \"" + responseToString(response) + " " + + retToString(response, sir) + + "\" to prevent \"ring of death\" bug."); + return; + } + } + + super.notifyRegistrantsCdmaInfoRec(infoRec); + } + + private void + handleNitzTimeReceived(Parcel p) { + String nitz = (String)responseString(p); + //if (RILJ_LOGD) unsljLogRet(RIL_UNSOL_NITZ_TIME_RECEIVED, nitz); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + String fixedNitz = nitz; + String[] nitzParts = nitz.split(","); + if (nitzParts.length == 4) { + // 0=date, 1=time+zone, 2=dst, 3=garbage that confuses GsmServiceStateTracker (so remove it) + fixedNitz = nitzParts[0]+","+nitzParts[1]+","+nitzParts[2]+","; + } + + result[0] = fixedNitz; + result[1] = Long.valueOf(nitzReceiveTime); + + boolean ignoreNitz = SystemProperties.getBoolean( + TelephonyProperties.PROPERTY_IGNORE_NITZ, false); + + if (ignoreNitz) { + if (RILJ_LOGD) riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED"); + } else { + if (mNITZTimeRegistrant != null) { + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = result; + } + } + } + + @Override + protected Object + responseSMS(Parcel p) { + // Notify that sendSMS() can send the next SMS + synchronized (mSMSLock) { + mIsSendingSMS = false; + mSMSLock.notify(); + } + + return super.responseSMS(p); + } +} diff --git a/src/java/com/android/internal/telephony/SemcQualcomm7x30RIL.java b/src/java/com/android/internal/telephony/SemcQualcomm7x30RIL.java new file mode 100644 index 0000000000..1b832915fa --- /dev/null +++ b/src/java/com/android/internal/telephony/SemcQualcomm7x30RIL.java @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2011-2013 The CyanogenMod 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 static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.os.AsyncResult; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Parcel; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.telephony.uicc.IccCardApplicationStatus; +import com.android.internal.telephony.dataconnection.DataCallResponse; +import com.android.internal.telephony.dataconnection.DcFailCause; + +import java.util.ArrayList; + +/** + * Custom Qualcomm No SimReady RIL for SEMC 7x30 Radio + * + * {@hide} + */ +public class SemcQualcomm7x30RIL extends RIL implements CommandsInterface { + protected String mAid = ""; + protected HandlerThread mIccThread; + protected IccHandler mIccHandler; + boolean RILJ_LOGV = true; + boolean RILJ_LOGD = true; + + private final int RIL_INT_RADIO_OFF = 0; + private final int RIL_INT_RADIO_UNAVALIABLE = 1; + private final int RIL_INT_RADIO_ON = 2; + + public SemcQualcomm7x30RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + mQANElements = 5; + } + + @Override + protected DataCallResponse getDataCallResponse(Parcel p, int version) { + DataCallResponse dataCall = new DataCallResponse(); + + dataCall.version = version; + if (version < 5) { + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + // DataCallResponse needs an ifname. Since we don't have one use the name from the ThrottleService resource (default=rmnet0). + dataCall.ifname = "rmnet0"; + } else { + dataCall.status = p.readInt(); + dataCall.suggestedRetryTime = p.readInt(); + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + dataCall.ifname = p.readString(); + if ((dataCall.status == DcFailCause.NONE.getErrorCode()) && + TextUtils.isEmpty(dataCall.ifname)) { + throw new RuntimeException("getDataCallResponse, no ifname"); + } + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + String dnses = p.readString(); + if (!TextUtils.isEmpty(dnses)) { + dataCall.dnses = dnses.split(" "); + } + String gateways = p.readString(); + if (!TextUtils.isEmpty(gateways)) { + dataCall.gateways = gateways.split(" "); + } + } + return dataCall; + } + + @Override public void + supplyIccPin(String pin, Message result) { + supplyIccPinForApp(pin, mAid, result); + } + + @Override public void + changeIccPin(String oldPin, String newPin, Message result) { + changeIccPinForApp(oldPin, newPin, mAid, result); + } + + @Override public void + supplyIccPin2(String pin, Message result) { + supplyIccPin2ForApp(pin, mAid, result); + } + + @Override public void + changeIccPin2(String oldPin2, String newPin2, Message result) { + changeIccPin2ForApp(oldPin2, newPin2, mAid, result); + } + + @Override public void + supplyIccPuk(String puk, String newPin, Message result) { + supplyIccPukForApp(puk, newPin, mAid, result); + } + + @Override public void + supplyIccPuk2(String puk2, String newPin2, Message result) { + supplyIccPuk2ForApp(puk2, newPin2, mAid, result); + } + + @Override + public void + queryFacilityLock(String facility, String password, int serviceClass, + Message response) { + queryFacilityLockForApp(facility, password, serviceClass, mAid, response); + } + + @Override + public void + setFacilityLock(String facility, boolean lockState, String password, + int serviceClass, Message response) { + setFacilityLockForApp(facility, lockState, password, serviceClass, mAid, response); + } + + @Override + public void + iccIO (int command, int fileid, String path, int p1, int p2, int p3, + String data, String pin2, Message result) { + iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, mAid, result); + } + + @Override + public void + getIMSI(Message result) { + getIMSIForApp(mAid, result); + } + + @Override + public void + getIMSIForApp(String aid, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); + + rr.mParcel.writeString(aid); + + if (RILJ_LOGD) riljLog(rr.serialString() + + "> getIMSI: " + requestToString(rr.mRequest) + + " aid: " + aid); + + send(rr); + } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + + rr.mParcel.writeString(address); + rr.mParcel.writeInt(clirMode); + rr.mParcel.writeInt(0); + + if (uusInfo == null) { + rr.mParcel.writeInt(0); // UUS information is absent + } else { + rr.mParcel.writeInt(1); // UUS information is present + rr.mParcel.writeInt(uusInfo.getType()); + rr.mParcel.writeInt(uusInfo.getDcs()); + rr.mParcel.writeByteArray(uusInfo.getUserData()); + } + rr.mParcel.writeInt(255); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setNetworkSelectionMode(String operatorNumeric, Message response) { + RILRequest rr; + + if (operatorNumeric == null) + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, response); + else + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, response); + + rr.mParcel.writeString(operatorNumeric); + rr.mParcel.writeInt(-1); + + send(rr); + } + + @Override + public void + setNetworkSelectionModeAutomatic(Message response) { + setNetworkSelectionMode(null, response); + } + + @Override + public void + setNetworkSelectionModeManual(String operatorNumeric, Message response) { + setNetworkSelectionMode(operatorNumeric, response); + } + + @Override + protected void + processUnsolicited (Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + case 1036: ret = responseVoid(p); break; // RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: + int state = p.readInt(); + setRadioStateFromRILInt(state); + break; + case 1036: + break; + } + } + + private void setRadioStateFromRILInt (int stateCode) { + CommandsInterface.RadioState radioState; + HandlerThread handlerThread; + Looper looper; + IccHandler iccHandler; + + switch (stateCode) { + case RIL_INT_RADIO_OFF: + radioState = CommandsInterface.RadioState.RADIO_OFF; + if (mIccHandler != null) { + mIccThread = null; + mIccHandler = null; + } + break; + case RIL_INT_RADIO_UNAVALIABLE: + radioState = CommandsInterface.RadioState.RADIO_UNAVAILABLE; + break; + case RIL_INT_RADIO_ON: + if (mIccHandler == null) { + handlerThread = new HandlerThread("IccHandler"); + mIccThread = handlerThread; + + mIccThread.start(); + + looper = mIccThread.getLooper(); + mIccHandler = new IccHandler(this,looper); + mIccHandler.run(); + } + radioState = CommandsInterface.RadioState.RADIO_ON; + break; + default: + throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); + } + + setRadioState (radioState); + } + + class IccHandler extends Handler implements Runnable { + private static final int EVENT_RADIO_ON = 1; + private static final int EVENT_ICC_STATUS_CHANGED = 2; + private static final int EVENT_GET_ICC_STATUS_DONE = 3; + private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 4; + + private RIL mRil; + private boolean mRadioOn = false; + + public IccHandler (RIL ril, Looper looper) { + super (looper); + mRil = ril; + } + + public void run () { + mRil.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); + Message msg = obtainMessage(EVENT_RADIO_ON); + mRil.getIccCardStatus(msg); + } + } +} diff --git a/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java index 51adce3c9d..cd47b71d1c 100644 --- a/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java +++ b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java @@ -84,8 +84,8 @@ public String toString() { .append(" cid=").append(cid) .append(" active=").append(active) .append(" type=").append(type) - .append(" ifname=").append(ifname) - .append(" mtu=").append(mtu) + .append("' ifname='").append(ifname); + sb.append("' addresses=["); .append(" addresses=["); for (String addr : addresses) { sb.append(addr); @@ -179,7 +179,7 @@ public SetupResult setLinkProperties(LinkProperties linkProperties, throw new UnknownHostException("Non-numeric dns addr=" + addr); } if (! ia.isAnyLocalAddress()) { - linkProperties.addDnsServer(ia); + linkProperties.addDns(ia); } } } else if (okToUseSystemPropertyDns){ @@ -196,7 +196,7 @@ public SetupResult setLinkProperties(LinkProperties linkProperties, throw new UnknownHostException("Non-numeric dns addr=" + dnsAddr); } if (! ia.isAnyLocalAddress()) { - linkProperties.addDnsServer(ia); + linkProperties.addDns(ia); } } } else { diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java index d83da44535..fc835c9bc3 100644 --- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java +++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java @@ -421,7 +421,7 @@ private DataConnection(PhoneBase phone, String name, int id, mDataRegState = mPhone.getServiceState().getDataRegState(); int networkType = ss.getDataNetworkType(); mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_MOBILE, - networkType, NETWORK_TYPE, TelephonyManager.getNetworkTypeName(networkType)); + networkType, "Cellular", TelephonyManager.getNetworkTypeName(networkType)); mNetworkInfo.setRoaming(ss.getRoaming()); mNetworkInfo.setIsAvailable(true); @@ -1590,14 +1590,14 @@ public boolean processMessage(Message msg) { + " result.isRestartRadioFail=" + result.mFailCause.isRestartRadioFail() + " result.isPermanentFail=" + - mDct.isPermanentFail(result.mFailCause)); + result.mFailCause.isPermanentFail()); } if (result.mFailCause.isRestartRadioFail()) { if (DBG) log("DcActivatingState: ERR_RilError restart radio"); mDct.sendRestartRadio(); mInactiveState.setEnterNotificationParams(cp, result.mFailCause); transitionTo(mInactiveState); - } else if (mDct.isPermanentFail(result.mFailCause)) { + } else if (result.mFailCause.isPermanentFail()) { if (DBG) log("DcActivatingState: ERR_RilError perm error"); mInactiveState.setEnterNotificationParams(cp, result.mFailCause); transitionTo(mInactiveState); @@ -1662,7 +1662,7 @@ public boolean processMessage(Message msg) { mDct.sendRestartRadio(); mInactiveState.setEnterNotificationParams(cp, cause); transitionTo(mInactiveState); - } else if (mDct.isPermanentFail(cause)) { + } else if (cause.isPermanentFail()) { if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE perm er"); mInactiveState.setEnterNotificationParams(cp, cause); transitionTo(mInactiveState); @@ -1954,6 +1954,7 @@ protected void unwanted() { } // this can only happen if our exit has been called - we're already disconnected if (mApnContexts == null) return; + for (ApnContext apnContext : mApnContexts) { Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, apnContext); DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg);