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

Commit 4548a35c authored by Aishwarya Mallampati's avatar Aishwarya Mallampati Committed by Jack Yu
Browse files

Added support for FDN Check in SMS.

If FDN is available and enabled, then sms to only numbers
present in the FDN list are allowed.

Bug: 218262162
Test: Manual
      atest FrameworksTelephonyTests:com.android.internal.telephony.FdnUtilsTest
      atest android.app.appops.cts.AppOpsLoggingTest#sendSms
Merged-In: I77f873fc34380f0101faf629da6d8ff0ec7a65ae
Change-Id: I77f873fc34380f0101faf629da6d8ff0ec7a65ae
parent ebef4a22
Loading
Loading
Loading
Loading
+17 −42
Original line number Original line Diff line number Diff line
@@ -16,9 +16,6 @@


package com.android.internal.telephony;
package com.android.internal.telephony;


import android.content.Context;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.TextUtils;


import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.NumberParseException;
@@ -36,7 +33,6 @@ import com.android.internal.telephony.uicc.UiccProfile;
import com.android.telephony.Rlog;
import com.android.telephony.Rlog;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Locale;


/**
/**
 * This is a basic utility class for common functions related to Fixed Dialing Numbers
 * This is a basic utility class for common functions related to Fixed Dialing Numbers
@@ -52,40 +48,30 @@ public class FdnUtils {
     * @param phoneId The phone object id for which the FDN check is performed
     * @param phoneId The phone object id for which the FDN check is performed
     * @param dialStr dialed phone number
     * @param dialStr dialed phone number
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @return true if dialStr is blocked due to FDN check.
     * @return {@code true} if dialStr is blocked due to FDN check.
     */
     */
    public static boolean isNumberBlockedByFDN(int phoneId, String dialStr,
    public static boolean isNumberBlockedByFDN(int phoneId, String dialStr,
            String defaultCountryIso) {
            String defaultCountryIso) {
        final UiccCardApplication app = getUiccCardApplication(phoneId);
        if (!isFdnEnabled(phoneId)) {

        if (!isFdnEnabled(app)) {
            return false;
            return false;
        }
        }


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


    /**
    /**
     * The following function checks if destination address or smsc is blocked due to FDN.
     * Checks if FDN is enabled
     * @param context context
     * @param phoneId The phone object id for which the FDN check is performed
     * @param subId subscription ID
     * @return {@code true} if FDN is enabled
     * @param destAddr destination address of the message
     * @param smscAddr smsc address of the subscription
     * @return true if either destAddr or smscAddr is blocked due to FDN.
     */
     */
    public static boolean isNumberBlockedByFDN(Context context, int subId, String destAddr,
    public static boolean isFdnEnabled(int phoneId) {
            String smscAddr) {
        UiccCardApplication app = getUiccCardApplication(phoneId);
        // Skip FDN check for emergency numbers
        if (app == null || (!app.getIccFdnAvailable())) {
        final TelephonyManager tm = context.getSystemService(TelephonyManager.class);
        if(tm.isEmergencyNumber(destAddr)) {
            return false;
            return false;
        }
        }


        final int phoneId = SubscriptionManager.getPhoneId(subId);
        return app.getIccFdnEnabled();
        final String defaultCountryIso = tm.getSimCountryIso().toUpperCase(Locale.ENGLISH);
        return (isNumberBlockedByFDN(phoneId, smscAddr, defaultCountryIso) ||
                isNumberBlockedByFDN(phoneId, destAddr, defaultCountryIso));
    }
    }


    /**
    /**
@@ -94,7 +80,7 @@ public class FdnUtils {
     * @param fdnList List of all FDN records associated with a sim card
     * @param fdnList List of all FDN records associated with a sim card
     * @param dialStr dialed phone number
     * @param dialStr dialed phone number
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @param defaultCountryIso country ISO for the subscription associated with this phone
     * @return true if dialStr is present in the fdnList.
     * @return {@code true} if dialStr is present in the fdnList.
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    public static boolean isFDN(String dialStr, String defaultCountryIso,
    public static boolean isFDN(String dialStr, String defaultCountryIso,
@@ -109,7 +95,7 @@ public class FdnUtils {
        String dialStrNational = null;
        String dialStrNational = null;
        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
        try {
        try {
            final PhoneNumber phoneNumber = phoneNumberUtil.parse(dialStr, defaultCountryIso);
            PhoneNumber phoneNumber = phoneNumberUtil.parse(dialStr, defaultCountryIso);
            dialStrE164 = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
            dialStrE164 = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
            dialStrNational = String.valueOf(phoneNumber.getNationalNumber());
            dialStrNational = String.valueOf(phoneNumber.getNationalNumber());
        } catch (NumberParseException ignored) {
        } catch (NumberParseException ignored) {
@@ -150,17 +136,18 @@ public class FdnUtils {
        return false;
        return false;
    }
    }


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


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


        final AdnRecordCache adnRecordCache = iccRecords.getAdnCache();
        AdnRecordCache adnRecordCache = iccRecords.getAdnCache();
        if(adnRecordCache == null) {
        if(adnRecordCache == null) {
            return null;
            return null;
        }
        }
@@ -168,20 +155,8 @@ public class FdnUtils {
        return adnRecordCache.getRecordsIfLoaded(IccConstants.EF_FDN);
        return adnRecordCache.getRecordsIfLoaded(IccConstants.EF_FDN);
    }
    }


    private static boolean isFdnEnabled(UiccCardApplication app) {
        if (app == null) {
            return false;
        }

        if (!app.getIccFdnAvailable()) {
            return false;
        }

        return app.getIccFdnEnabled();
    }

    private static UiccCardApplication getUiccCardApplication(int phoneId) {
    private static UiccCardApplication getUiccCardApplication(int phoneId) {
        final UiccProfile uiccProfile = UiccController.getInstance()
        UiccProfile uiccProfile = UiccController.getInstance()
                .getUiccProfileForPhone(phoneId);
                .getUiccProfileForPhone(phoneId);
        if (uiccProfile == null) {
        if (uiccProfile == null) {
            return null;
            return null;
+81 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.List;
import java.util.Locale;


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

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

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

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

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

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

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

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

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

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

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

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