Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 844817ae authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ifde290a1,I77f873fc,I8165d5e6

* changes:
  Added support for FDN Check in Supplementary Services(SS).
  Added support for FDN Check in SMS.
  Bring back "Added support for FDN Check."
parents 8e1f2ed9 8c54c1dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ public class CallStateException extends Exception
    public static final int ERROR_CALLING_DISABLED = 5;
    public static final int ERROR_TOO_MANY_CALLS = 6;
    public static final int ERROR_OTASP_PROVISIONING_IN_PROCESS = 7;
    public static final int ERROR_FDN_BLOCKED = 8;

    public
    CallStateException()
+190 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import android.text.TextUtils;

import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.uicc.AdnRecord;
import com.android.internal.telephony.uicc.AdnRecordCache;
import com.android.internal.telephony.uicc.IccConstants;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccCardApplication;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.telephony.Rlog;

import java.util.ArrayList;

/**
 * This is a basic utility class for common functions related to Fixed Dialing Numbers
 * designed as per 3GPP 22.101.
 */
public class FdnUtils {
    private static final boolean VDBG = false;
    private static final String LOG_TAG = FdnUtils.class.getSimpleName();

    /**
     * The following function checks if dialed number is blocked due to FDN.
     *
     * @param phoneId The phone object id for which the FDN check is performed
     * @param dialStr dialed phone number
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @return {@code true} if dialStr is blocked due to FDN check.
     */
    public static boolean isNumberBlockedByFDN(int phoneId, String dialStr,
            String defaultCountryIso) {
        if (!isFdnEnabled(phoneId)) {
            return false;
        }

        ArrayList<AdnRecord> fdnList = getFdnList(phoneId);
        return !isFDN(dialStr, defaultCountryIso, fdnList);
    }

    /**
     * Checks if FDN is enabled
     * @param phoneId The phone object id for which the FDN check is performed
     * @return {@code true} if FDN is enabled
     */
    public static boolean isFdnEnabled(int phoneId) {
        UiccCardApplication app = getUiccCardApplication(phoneId);
        if (app == null || (!app.getIccFdnAvailable())) {
            return false;
        }

        return app.getIccFdnEnabled();
    }

    /**
     * If FDN is enabled, check to see if the given supplementary service control strings are
     * blocked due to FDN.
     * @param phoneId The phone object id for which the FDN check is performed
     * @param controlStrings control strings associated with the supplementary service request
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @return {@code true} if the FDN list does not contain any of the control strings.
     */
    public static boolean isSuppServiceRequestBlockedByFdn(int phoneId,
            ArrayList<String> controlStrings, String defaultCountryIso) {
        if (!isFdnEnabled(phoneId)) {
            return false;
        }

        ArrayList<AdnRecord> fdnList = getFdnList(phoneId);
        for(String controlString : controlStrings) {
            if(isFDN(controlString, defaultCountryIso, fdnList)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Checks if dialStr is part of FDN list.
     *
     * @param fdnList List of all FDN records associated with a sim card
     * @param dialStr dialed phone number
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @return {@code true} if dialStr is present in the fdnList.
     */
    @VisibleForTesting
    public static boolean isFDN(String dialStr, String defaultCountryIso,
            ArrayList<AdnRecord> fdnList) {
        if (fdnList == null || fdnList.isEmpty() || TextUtils.isEmpty(dialStr)) {
            Rlog.w(LOG_TAG, "isFDN: unexpected null value");
            return false;
        }

        // Parse the dialStr and convert it to E164 format
        String dialStrE164 = null;
        String dialStrNational = null;
        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
        try {
            PhoneNumber phoneNumber = phoneNumberUtil.parse(dialStr, defaultCountryIso);
            dialStrE164 = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
            dialStrNational = String.valueOf(phoneNumber.getNationalNumber());
        } catch (NumberParseException ignored) {
            Rlog.w(LOG_TAG, "isFDN: could not parse dialStr");
        }

        /**
         * Returns true if dialStrE164 or dialStrNational or dialStr starts with fdnNumber
         * E.g.1: returns true if fdnNumber="123" and dialStr="12345"
         * E.g.2: does not return true if fdnNumber="1123" and dialStr="12345"
         */
        for (AdnRecord fdn: fdnList) {
            String fdnNumber = fdn.getNumber();
            if (TextUtils.isEmpty(fdnNumber)) {
                continue;
            }

            if(!TextUtils.isEmpty(dialStrE164)) {
                if(dialStrE164.startsWith(fdnNumber)) {
                    return true;
                }
            }

            if(!TextUtils.isEmpty(dialStrNational)) {
                if (dialStrNational.startsWith(fdnNumber)) {
                    return true;
                }
            }

            if (dialStr.startsWith(fdnNumber)) {
                return true;
            }
        }

        if (VDBG) {
            Rlog.i(LOG_TAG, "isFDN: dialed number not present in FDN list");
        }
        return false;
    }

    private static ArrayList<AdnRecord> getFdnList(int phoneId) {
        UiccCardApplication app = getUiccCardApplication(phoneId);
        if (app == null) {
            return null;
        }

        IccRecords iccRecords = app.getIccRecords();
        if (iccRecords == null) {
            return null;
        }

        AdnRecordCache adnRecordCache = iccRecords.getAdnCache();
        if(adnRecordCache == null) {
            return null;
        }

        return adnRecordCache.getRecordsIfLoaded(IccConstants.EF_FDN);
    }

    private static UiccCardApplication getUiccCardApplication(int phoneId) {
        UiccProfile uiccProfile = UiccController.getInstance()
                .getUiccProfileForPhone(phoneId);
        if (uiccProfile == null) {
            return null;
        }

        return uiccProfile.getApplication(UiccController.APP_FAM_3GPP);
    }
}
 No newline at end of file
+121 −1
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ import com.android.internal.telephony.data.DataNetworkController;
import com.android.internal.telephony.data.LinkBandwidthEstimator;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.gsm.GsmMmiCode;
import com.android.internal.telephony.gsm.SsData;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
@@ -1388,6 +1389,12 @@ public class GsmCdmaPhone extends Phone {
                    + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A"));
        }

        // Perform FDN check for non-emergency calls - shouldn't dial if number is blocked by FDN
        if(!isEmergency && FdnUtils.isNumberBlockedByFDN(mPhoneId, dialString, getCountryIso())) {
            throw new CallStateException(CallStateException.ERROR_FDN_BLOCKED,
                    "cannot dial number blocked by FDN");
        }

        // Bypass WiFi Only WFC check if this is an emergency call - we should still try to
        // place over cellular if possible.
        if (!isEmergency) {
@@ -1585,6 +1592,13 @@ public class GsmCdmaPhone extends Phone {
            return true;
        }

        // Perform FDN check
        if(FdnUtils.isNumberBlockedByFDN(mPhoneId, ussdRequest, getCountryIso())) {
            sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE,
                    wrappedCallback );
            return true;
        }

        // Try over IMS if possible.
        Phone imsPhone = mImsPhone;
        if ((imsPhone != null)
@@ -2228,6 +2242,15 @@ public class GsmCdmaPhone extends Phone {
    @Override
    public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
            Message onComplete) {
        // Perform FDN check
        SsData.ServiceType serviceType = GsmMmiCode.cfReasonToServiceType(commandInterfaceCFReason);
        if(isRequestBlockedByFDN(SsData.RequestType.SS_INTERROGATION, serviceType)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.getCallForwardingOption(commandInterfaceCFReason, serviceClass, onComplete);
@@ -2277,6 +2300,16 @@ public class GsmCdmaPhone extends Phone {
            int serviceClass,
            int timerSeconds,
            Message onComplete) {
        // Perform FDN check
        SsData.RequestType requestType = GsmMmiCode.cfActionToRequestType(commandInterfaceCFAction);
        SsData.ServiceType serviceType = GsmMmiCode.cfReasonToServiceType(commandInterfaceCFReason);
        if(isRequestBlockedByFDN(requestType, serviceType)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason,
@@ -2330,6 +2363,15 @@ public class GsmCdmaPhone extends Phone {
    @Override
    public void getCallBarring(String facility, String password, Message onComplete,
            int serviceClass) {
        // Perform FDN check
        SsData.ServiceType serviceType = GsmMmiCode.cbFacilityToServiceType(facility);
        if (isRequestBlockedByFDN(SsData.RequestType.SS_INTERROGATION, serviceType)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.getCallBarring(facility, password, onComplete, serviceClass);
@@ -2346,6 +2388,17 @@ public class GsmCdmaPhone extends Phone {
    @Override
    public void setCallBarring(String facility, boolean lockState, String password,
            Message onComplete, int serviceClass) {
        // Perform FDN check
        SsData.RequestType requestType = lockState ? SsData.RequestType.SS_ACTIVATION :
                SsData.RequestType.SS_DEACTIVATION;
        SsData.ServiceType serviceType = GsmMmiCode.cbFacilityToServiceType(facility);
        if (isRequestBlockedByFDN(requestType, serviceType)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.setCallBarring(facility, lockState, password, onComplete, serviceClass);
@@ -2369,6 +2422,18 @@ public class GsmCdmaPhone extends Phone {
     */
    public void changeCallBarringPassword(String facility, String oldPwd, String newPwd,
            Message onComplete) {
        // Perform FDN check
        SsData.ServiceType serviceType = GsmMmiCode.cbFacilityToServiceType(facility);
        ArrayList<String> controlStrings = GsmMmiCode.getControlStringsForPwd(
                SsData.RequestType.SS_REGISTRATION,
                serviceType);
        if(FdnUtils.isSuppServiceRequestBlockedByFdn(mPhoneId, controlStrings, getCountryIso())) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        if (isPhoneTypeGsm()) {
            mCi.changeBarringPassword(facility, oldPwd, newPwd, onComplete);
        } else {
@@ -2378,6 +2443,14 @@ public class GsmCdmaPhone extends Phone {

    @Override
    public void getOutgoingCallerIdDisplay(Message onComplete) {
        // Perform FDN check
        if(isRequestBlockedByFDN(SsData.RequestType.SS_INTERROGATION, SsData.ServiceType.SS_CLIR)){
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.getOutgoingCallerIdDisplay(onComplete);
@@ -2396,6 +2469,15 @@ public class GsmCdmaPhone extends Phone {

    @Override
    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
        // Perform FDN check
        SsData.RequestType requestType = GsmMmiCode.clirModeToRequestType(commandInterfaceCLIRMode);
        if (isRequestBlockedByFDN(requestType, SsData.ServiceType.SS_CLIR)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode, onComplete);
@@ -2418,6 +2500,14 @@ public class GsmCdmaPhone extends Phone {

    @Override
    public void queryCLIP(Message onComplete) {
        // Perform FDN check
        if(isRequestBlockedByFDN(SsData.RequestType.SS_INTERROGATION, SsData.ServiceType.SS_CLIP)){
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.queryCLIP(onComplete);
@@ -2436,6 +2526,14 @@ public class GsmCdmaPhone extends Phone {

    @Override
    public void getCallWaiting(Message onComplete) {
        // Perform FDN check
        if(isRequestBlockedByFDN(SsData.RequestType.SS_INTERROGATION, SsData.ServiceType.SS_WAIT)){
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.getCallWaiting(onComplete);
@@ -2477,6 +2575,16 @@ public class GsmCdmaPhone extends Phone {

    @Override
    public void setCallWaiting(boolean enable, int serviceClass, Message onComplete) {
        // Perform FDN check
        SsData.RequestType requestType = enable ? SsData.RequestType.SS_ACTIVATION :
                SsData.RequestType.SS_DEACTIVATION;
        if (isRequestBlockedByFDN(requestType, SsData.ServiceType.SS_WAIT)) {
            AsyncResult.forMessage(onComplete, null,
                    new CommandException(CommandException.Error.FDN_CHECK_FAILURE));
            onComplete.sendToTarget();
            return;
        }

        Phone imsPhone = mImsPhone;
        if (useSsOverIms(onComplete)) {
            imsPhone.setCallWaiting(enable, onComplete);
@@ -4742,4 +4850,16 @@ public class GsmCdmaPhone extends Phone {
    public InboundSmsHandler getInboundSmsHandler(boolean is3gpp2) {
        return mIccSmsInterfaceManager.getInboundSmsHandler(is3gpp2);
    }

    /**
     * The following function checks if supplementary service request is blocked due to FDN.
     * @param requestType request type associated with the supplementary service
     * @param serviceType supplementary service type
     * @return {@code true} if request is blocked due to FDN.
     */
    private boolean isRequestBlockedByFDN(SsData.RequestType requestType,
            SsData.ServiceType serviceType) {
        ArrayList<String> controlStrings = GsmMmiCode.getControlStrings(requestType, serviceType);
        return FdnUtils.isSuppServiceRequestBlockedByFdn(mPhoneId, controlStrings, getCountryIso());
    }
}
 No newline at end of file
+81 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Locale;

/**
 * Implements the ISmsImplBase interface used in the SmsManager API.
@@ -151,6 +152,13 @@ public class SmsController extends ISmsImplBase {
        if (callingPackage == null) {
            callingPackage = getCallingPackage();
        }

        // Perform FDN check
        if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
            return;
        }

        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
        if (iccSmsIntMgr != null) {
            iccSmsIntMgr.sendData(callingPackage, callingAttributionTag, destAddr, scAddr, destPort,
@@ -194,6 +202,13 @@ public class SmsController extends ISmsImplBase {
            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
            return;
        }

        // Perform FDN check
        if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
            return;
        }

        long token = Binder.clearCallingIdentity();
        SubscriptionInfo info;
        try {
@@ -201,6 +216,7 @@ public class SmsController extends ISmsImplBase {
        } finally {
            Binder.restoreCallingIdentity(token);
        }

        if (isBluetoothSubscription(info)) {
            sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent);
        } else {
@@ -259,6 +275,13 @@ public class SmsController extends ISmsImplBase {
        if (callingPackage == null) {
            callingPackage = getCallingPackage();
        }

        // Perform FDN check
        if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
            return;
        }

        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
        if (iccSmsIntMgr != null) {
            iccSmsIntMgr.sendTextWithOptions(callingPackage, callingAttributionTag, destAddr,
@@ -281,6 +304,13 @@ public class SmsController extends ISmsImplBase {
        if (getCallingPackage() != null) {
            callingPackage = getCallingPackage();
        }

        // Perform FDN check
        if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
            sendErrorInPendingIntents(sentIntents, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
            return;
        }

        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
        if (iccSmsIntMgr != null) {
            iccSmsIntMgr.sendMultipartText(callingPackage, callingAttributionTag, destAddr, scAddr,
@@ -301,6 +331,13 @@ public class SmsController extends ISmsImplBase {
        if (callingPackage == null) {
            callingPackage = getCallingPackage();
        }

        // Perform FDN check
        if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
            sendErrorInPendingIntents(sentIntents, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
            return;
        }

        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
        if (iccSmsIntMgr != null) {
            iccSmsIntMgr.sendMultipartTextWithOptions(callingPackage, callingAttributionTag,
@@ -856,4 +893,48 @@ public class SmsController extends ISmsImplBase {
    public static String formatCrossStackMessageId(long id) {
        return "{x-message-id:" + id + "}";
    }

    /**
     * The following function checks if destination address or smsc is blocked due to FDN.
     * @param subId subscription ID
     * @param destAddr destination address of the message
     * @return true if either destAddr or smscAddr is blocked due to FDN.
     */
    private boolean isNumberBlockedByFDN(int subId, String destAddr, String callingPackage) {
        int phoneId = SubscriptionManager.getPhoneId(subId);
        if (!FdnUtils.isFdnEnabled(phoneId)) {
            return false;
        }

        // Skip FDN check for emergency numbers
        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
        if (tm.isEmergencyNumber(destAddr)) {
            return false;
        }

        // Check if destAddr is present in FDN list
        String defaultCountryIso = tm.getSimCountryIso().toUpperCase(Locale.ENGLISH);
        if (FdnUtils.isNumberBlockedByFDN(phoneId, destAddr, defaultCountryIso)) {
            return true;
        }

        // Get SMSC address for this subscription
        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
        String smscAddr;
        if (iccSmsIntMgr != null) {
            long identity = Binder.clearCallingIdentity();
            try {
                smscAddr =  iccSmsIntMgr.getSmscAddressFromIccEf(callingPackage);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        } else {
            Rlog.e(LOG_TAG, "getSmscAddressFromIccEfForSubscriber iccSmsIntMgr is null"
                + " for Subscription: " + subId);
            return true;
        }

        // Check if smscAddr is present in FDN list
        return FdnUtils.isNumberBlockedByFDN(phoneId, smscAddr, defaultCountryIso);
    }
}
+184 −1

File changed.

Preview size limit exceeded, changes collapsed.

Loading