• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }