1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.text.TextUtils; 20 21 import com.android.i18n.phonenumbers.NumberParseException; 22 import com.android.i18n.phonenumbers.PhoneNumberUtil; 23 import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; 24 import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber; 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.internal.telephony.uicc.AdnRecord; 27 import com.android.internal.telephony.uicc.AdnRecordCache; 28 import com.android.internal.telephony.uicc.IccConstants; 29 import com.android.internal.telephony.uicc.IccRecords; 30 import com.android.internal.telephony.uicc.UiccCardApplication; 31 import com.android.internal.telephony.uicc.UiccController; 32 import com.android.internal.telephony.uicc.UiccProfile; 33 import com.android.telephony.Rlog; 34 35 import java.util.ArrayList; 36 37 /** 38 * This is a basic utility class for common functions related to Fixed Dialing Numbers 39 * designed as per 3GPP 22.101. 40 */ 41 public class FdnUtils { 42 private static final boolean VDBG = false; 43 private static final String LOG_TAG = FdnUtils.class.getSimpleName(); 44 45 /** 46 * The following function checks if dialed number is blocked due to FDN. 47 * 48 * @param phoneId The phone object id for which the FDN check is performed 49 * @param dialStr dialed phone number 50 * @param defaultCountryIso country ISO for the subscription associated with this phone 51 * @return {@code true} if dialStr is blocked due to FDN check. 52 */ isNumberBlockedByFDN(int phoneId, String dialStr, String defaultCountryIso)53 public static boolean isNumberBlockedByFDN(int phoneId, String dialStr, 54 String defaultCountryIso) { 55 if (!isFdnEnabled(phoneId)) { 56 return false; 57 } 58 59 ArrayList<AdnRecord> fdnList = getFdnList(phoneId); 60 return !isFDN(dialStr, defaultCountryIso, fdnList); 61 } 62 63 /** 64 * Checks if FDN is enabled 65 * @param phoneId The phone object id for which the FDN check is performed 66 * @return {@code true} if FDN is enabled 67 */ isFdnEnabled(int phoneId)68 public static boolean isFdnEnabled(int phoneId) { 69 UiccCardApplication app = getUiccCardApplication(phoneId); 70 if (app == null || (!app.getIccFdnAvailable())) { 71 return false; 72 } 73 74 return app.getIccFdnEnabled(); 75 } 76 77 /** 78 * If FDN is enabled, check to see if the given supplementary service control strings are 79 * blocked due to FDN. 80 * @param phoneId The phone object id for which the FDN check is performed 81 * @param controlStrings control strings associated with the supplementary service request 82 * @param defaultCountryIso country ISO for the subscription associated with this phone 83 * @return {@code true} if the FDN list does not contain any of the control strings. 84 */ isSuppServiceRequestBlockedByFdn(int phoneId, ArrayList<String> controlStrings, String defaultCountryIso)85 public static boolean isSuppServiceRequestBlockedByFdn(int phoneId, 86 ArrayList<String> controlStrings, String defaultCountryIso) { 87 if (!isFdnEnabled(phoneId)) { 88 return false; 89 } 90 91 ArrayList<AdnRecord> fdnList = getFdnList(phoneId); 92 for(String controlString : controlStrings) { 93 if(isFDN(controlString, defaultCountryIso, fdnList)) { 94 return false; 95 } 96 } 97 return true; 98 } 99 100 /** 101 * Checks if dialStr is part of FDN list. 102 * 103 * @param fdnList List of all FDN records associated with a sim card 104 * @param dialStr dialed phone number 105 * @param defaultCountryIso country ISO for the subscription associated with this phone 106 * @return {@code true} if dialStr is present in the fdnList. 107 */ 108 @VisibleForTesting isFDN(String dialStr, String defaultCountryIso, ArrayList<AdnRecord> fdnList)109 public static boolean isFDN(String dialStr, String defaultCountryIso, 110 ArrayList<AdnRecord> fdnList) { 111 if (fdnList == null || fdnList.isEmpty() || TextUtils.isEmpty(dialStr)) { 112 Rlog.w(LOG_TAG, "isFDN: unexpected null value"); 113 return false; 114 } 115 116 // Parse the dialStr and convert it to E164 format 117 String dialStrE164 = null; 118 String dialStrNational = null; 119 final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); 120 try { 121 PhoneNumber phoneNumber = phoneNumberUtil.parse(dialStr, defaultCountryIso); 122 dialStrE164 = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164); 123 dialStrNational = String.valueOf(phoneNumber.getNationalNumber()); 124 } catch (NumberParseException ignored) { 125 Rlog.w(LOG_TAG, "isFDN: could not parse dialStr"); 126 } 127 128 /** 129 * Returns true if dialStrE164 or dialStrNational or dialStr starts with fdnNumber 130 * E.g.1: returns true if fdnNumber="123" and dialStr="12345" 131 * E.g.2: does not return true if fdnNumber="1123" and dialStr="12345" 132 */ 133 for (AdnRecord fdn: fdnList) { 134 String fdnNumber = fdn.getNumber(); 135 if (TextUtils.isEmpty(fdnNumber)) { 136 continue; 137 } 138 139 if(!TextUtils.isEmpty(dialStrE164)) { 140 if(dialStrE164.startsWith(fdnNumber)) { 141 return true; 142 } 143 } 144 145 if(!TextUtils.isEmpty(dialStrNational)) { 146 if (dialStrNational.startsWith(fdnNumber)) { 147 return true; 148 } 149 } 150 151 if (dialStr.startsWith(fdnNumber)) { 152 return true; 153 } 154 } 155 156 if (VDBG) { 157 Rlog.i(LOG_TAG, "isFDN: dialed number not present in FDN list"); 158 } 159 return false; 160 } 161 getFdnList(int phoneId)162 private static ArrayList<AdnRecord> getFdnList(int phoneId) { 163 UiccCardApplication app = getUiccCardApplication(phoneId); 164 if (app == null) { 165 return null; 166 } 167 168 IccRecords iccRecords = app.getIccRecords(); 169 if (iccRecords == null) { 170 return null; 171 } 172 173 AdnRecordCache adnRecordCache = iccRecords.getAdnCache(); 174 if(adnRecordCache == null) { 175 return null; 176 } 177 178 return adnRecordCache.getRecordsIfLoaded(IccConstants.EF_FDN); 179 } 180 getUiccCardApplication(int phoneId)181 private static UiccCardApplication getUiccCardApplication(int phoneId) { 182 UiccProfile uiccProfile = UiccController.getInstance() 183 .getUiccProfileForPhone(phoneId); 184 if (uiccProfile == null) { 185 return null; 186 } 187 188 return uiccProfile.getApplication(UiccController.APP_FAM_3GPP); 189 } 190 }