/* * Copyright (C) 2014 MediaTek Inc. */ /* * Copyright (C) 2016 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.os.SystemProperties; import android.telephony.PhoneNumberUtils; import android.telephony.Rlog; import android.text.TextUtils; import java.util.ArrayList; import java.util.HashMap; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.FileReader; import java.io.IOException; public class MtkEccList extends PhoneNumberUtils { static final String LOG_TAG = "MtkEccList"; private static ArrayList mCustomizedEccList = null; private static HashMap mHashMapForNetworkEccCategory = null; private static boolean sIsCtaSet = true; static { sIsCtaSet = "1".equals(SystemProperties.get("ro.mtk_cta_set")); mCustomizedEccList = new ArrayList(); parseEccList(); mHashMapForNetworkEccCategory = new HashMap(); } /** @hide */ public static class EccEntry { public static final String ECC_LIST_PATH = "/system/etc/ecc_list.xml"; public static final String ECC_ENTRY_TAG = "EccEntry"; public static final String ECC_ATTR = "Ecc"; public static final String CATEGORY_ATTR = "Category"; public static final String CONDITION_ATTR = "Condition"; public static final String ECC_NO_SIM = "0"; public static final String ECC_ALWAYS = "1"; public static final String ECC_FOR_MMI = "2"; private String mEcc; private String mCategory; private String mCondition; // ECC_NO_SIM, ECC_ALWAYS, or ECC_FOR_MMI public EccEntry() { mEcc = new String(""); mCategory = new String(""); mCondition = new String(""); } public void setEcc(String strEcc) { mEcc = strEcc; } public void setCategory(String strCategory) { mCategory = strCategory; } public void setCondition(String strCondition) { mCondition = strCondition; } public String getEcc() { return mEcc; } public String getCategory() { return mCategory; } public String getCondition() { return mCondition; } @Override public String toString() { return ("\n" + ECC_ATTR + "=" + getEcc() + ", " + CATEGORY_ATTR + "=" + getCategory() + ", " + CONDITION_ATTR + "=" + getCondition()); } } /** * Parse Ecc List From XML File * * @param none. * @return none. * @hide */ private static void parseEccList() { mCustomizedEccList.clear(); // Parse GSM ECC list try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); if (parser == null) { Rlog.d(LOG_TAG, "XmlPullParserFactory.newPullParser() return null"); return; } FileReader fileReader = new FileReader(EccEntry.ECC_LIST_PATH); parser.setInput(fileReader); int eventType = parser.getEventType(); EccEntry record = null; while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: if (parser.getName().equals(EccEntry.ECC_ENTRY_TAG)) { record = new EccEntry(); int attrNum = parser.getAttributeCount(); for (int i = 0; i < attrNum; ++i) { String name = parser.getAttributeName(i); String value = parser.getAttributeValue(i); if (name.equals(EccEntry.ECC_ATTR)) record.setEcc(value); else if (name.equals(EccEntry.CATEGORY_ATTR)) record.setCategory(value); else if (name.equals(EccEntry.CONDITION_ATTR)) record.setCondition(value); } } break; case XmlPullParser.END_TAG: if (parser.getName().equals(EccEntry.ECC_ENTRY_TAG) && record != null) mCustomizedEccList.add(record); break; } eventType = parser.next(); } fileReader.close(); if (sIsCtaSet) { String [] emergencyCTAList = {"120", "122", "110", "119"}; for (String emergencyNum : emergencyCTAList) { record = new EccEntry(); record.setEcc(emergencyNum); record.setCategory("0"); record.setCondition(EccEntry.ECC_FOR_MMI); boolean bFound = false; int nIndex = 0; for (EccEntry eccEntry : mCustomizedEccList) { String ecc = eccEntry.getEcc(); if (ecc.equals(emergencyNum)) { bFound = true; Rlog.d(LOG_TAG, "[parseEccList]" + "CTA ecc match customized ecc list, ecc=" + ecc); break; } nIndex++; } if (bFound) mCustomizedEccList.set(nIndex, record); else mCustomizedEccList.add(record); } } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static boolean isEmergencyNumberExt(String number) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt], number:" + number ); if (number == null) { return false; } String numberPlus = null; boolean bSIMInserted = false; // Strip the separators from the number before comparing it // to the list. number = extractNetworkPortionAlt(number); // 1. Check ECCs updated by network mHashMapForNetworkEccCategory.clear(); String strEccCategoryList = SystemProperties.get("ril.ecc.service.category.list"); if (!TextUtils.isEmpty(strEccCategoryList)) { for (String strEccCategory : strEccCategoryList.split(";")) { if (!strEccCategory.isEmpty()) { String[] strEccCategoryAry = strEccCategory.split(","); if (2 == strEccCategoryAry.length) { mHashMapForNetworkEccCategory.put(strEccCategoryAry[0], Integer.parseInt(strEccCategoryAry[1])); } } } } for (String emergencyNum : mHashMapForNetworkEccCategory.keySet()) { numberPlus = emergencyNum + "+"; if (emergencyNum.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt] match network ecc list"); return true; } } // 2. Check ECCs stored at SIMs // Read from SIM1 String numbers = SystemProperties.get("ril.ecclist"); Rlog.d(LOG_TAG, "[isEmergencyNumberExt] ril.ecclist: " + numbers); if (!TextUtils.isEmpty(numbers)) { // searches through the comma-separated list for a match, // return true if one is found. for (String emergencyNum : numbers.split(",")) { numberPlus = emergencyNum + "+"; if (emergencyNum.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt] match ril.ecclist"); return true; } } bSIMInserted = true; } // Read from SIM2 numbers = SystemProperties.get("ril.ecclist1"); Rlog.d(LOG_TAG, "[isEmergencyNumberExt] ril.ecclist1: " + numbers); if (!TextUtils.isEmpty(numbers)) { // searches through the comma-separated list for a match, // return true if one is found. for (String emergencyNum : numbers.split(",")) { numberPlus = emergencyNum + "+"; if (emergencyNum.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt] match ril.ecclist1"); return true; } } bSIMInserted = true; } // 3. Check ECCs customized by user if (bSIMInserted) { if (mCustomizedEccList != null) { for (EccEntry eccEntry : mCustomizedEccList) { if (!eccEntry.getCondition().equals(EccEntry.ECC_NO_SIM)) { String ecc = eccEntry.getEcc(); numberPlus = ecc + "+"; if (ecc.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt] match" + " customized ecc list"); return true; } } } } } else { if (mCustomizedEccList != null) { for (EccEntry eccEntry : mCustomizedEccList) { String ecc = eccEntry.getEcc(); numberPlus = ecc + "+"; if (ecc.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[isEmergencyNumberExt] match" + " customized ecc list when no sim"); return true; } } } } Rlog.d(LOG_TAG, "[isEmergencyNumberExt] no match"); return false; } /** * Get the service category for the given ECC number. * @param number The ECC number. * @return The service category for the given number. * @hide */ public static int getServiceCategoryFromEcc(String number) { String numberPlus = null; // 1. Get category from network for (String emergencyNum : mHashMapForNetworkEccCategory.keySet()) { numberPlus = emergencyNum + "+"; if (emergencyNum.equals(number) || numberPlus.equals(number)) { Integer nSC = mHashMapForNetworkEccCategory.get(emergencyNum); if (nSC != null) { Rlog.d(LOG_TAG, "[getServiceCategoryFromEcc] match network ecc list, " + "Ecc= " + number + ", Category= " + nSC); return nSC; } } } // 2. Get category from sim // ToDo: EF_Ecc will convey service category later // 3. Get category from user-customized if (mCustomizedEccList != null) { for (EccEntry eccEntry : mCustomizedEccList) { String ecc = eccEntry.getEcc(); numberPlus = ecc + "+"; if (ecc.equals(number) || numberPlus.equals(number)) { Rlog.d(LOG_TAG, "[getServiceCategoryFromEcc] match customized ecc list, " + "Ecc= " + ecc + ", Category= " + eccEntry.getCategory()); return Integer.parseInt(eccEntry.getCategory()); } } } Rlog.d(LOG_TAG, "[getServiceCategoryFromEcc] no matched for Ecc =" + number + ", return 0"); return 0; } public static void updateEmergencyNumbersProperty() { ArrayList sim1List = new ArrayList(); ArrayList sim2List = new ArrayList(); ArrayList fixedList = new ArrayList(); ArrayList fixedListNoSim = new ArrayList(); if (mCustomizedEccList != null) { for (EccEntry eccEntry : mCustomizedEccList) { String ecc = eccEntry.getEcc(); if (!eccEntry.getCondition().equals(EccEntry.ECC_NO_SIM)) { fixedList.add(ecc); } else if (!TextUtils.isEmpty(ecc)) { fixedListNoSim.add(ecc); } } } // Read from SIM1 String numbers = SystemProperties.get("ril.ecclist"); for (String emergencyNum : numbers.split(",")) { if (!TextUtils.isEmpty(emergencyNum)) sim1List.add(emergencyNum); } // dedupe sim1List.removeAll(fixedList); sim1List.addAll(fixedList); if (TextUtils.isEmpty(numbers)) { sim1List.removeAll(fixedListNoSim); sim1List.addAll(fixedListNoSim); } SystemProperties.set("ril.ecclist",TextUtils.join(",", sim1List)); // Read from SIM2 numbers = SystemProperties.get("ril.ecclist1"); for (String emergencyNum : numbers.split(",")) { if (!TextUtils.isEmpty(emergencyNum)) sim2List.add(emergencyNum); } // dedupe sim2List.removeAll(fixedList); sim2List.addAll(fixedList); if (TextUtils.isEmpty(numbers)) { sim2List.removeAll(fixedListNoSim); sim2List.addAll(fixedListNoSim); } SystemProperties.set("ril.ecclist1",TextUtils.join(",", sim2List)); } }