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

Commit de228f84 authored by Ta-wei Yen's avatar Ta-wei Yen Committed by android-build-merger
Browse files

Add carrier regex filtering to VisualVoicemailSmsFilter

am: 585c4649

Change-Id: I20fa9747bd3c892cd6c513af5acb59e58b812beb
parents 9e8878fd 585c4649
Loading
Loading
Loading
Loading
+69 −13
Original line number Diff line number Diff line
@@ -15,17 +15,21 @@
 */
package com.android.internal.telephony;

import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.provider.VoicemailContract;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.telephony.VisualVoicemailSmsParser.WrappedMessageData;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class VisualVoicemailSmsFilter {

@@ -33,6 +37,8 @@ public class VisualVoicemailSmsFilter {

    private static final String SYSTEM_VVM_CLIENT_PACKAGE = "com.android.phone";

    private static Map<String, List<Pattern>> sPatterns;

    /**
     * Attempt to parse the incoming SMS as a visual voicemail SMS. If the parsing succeeded, A
     * {@link VoicemailContract.ACTION_VOICEMAIL_SMS_RECEIVED} intent will be sent to the visual
@@ -42,6 +48,11 @@ public class VisualVoicemailSmsFilter {
     *
     * <p>[clientPrefix]:[prefix]:([key]=[value];)*
     *
     * Additionally, if the SMS does not match the format, but matches the regex specified by the
     * carrier in {@link com.android.internal.R.array.config_vvmSmsFilterRegexes}, the SMS will
     * still be dropped and a {@link VoicemailContract.ACTION_VOICEMAIL_SMS_RECEIVED} with {@link
     * VoicemailContract#EXTRA_VOICEMAIL_SMS_MESSAGE_BODY} will be sent.
     *
     * @return true if the SMS has been parsed to be a visual voicemail SMS and should be dropped
     */
    public static boolean filter(Context context, byte[][] pdus, String format, int destPort,
@@ -69,34 +80,79 @@ public class VisualVoicemailSmsFilter {
            WrappedMessageData messageData = VisualVoicemailSmsParser
                .parseAlternativeFormat(asciiMessage);
            if (messageData != null) {
                sendVvmSmsBroadcast(context, vvmClientPackage, subId, messageData);
                sendVvmSmsBroadcast(context, vvmClientPackage, subId, messageData, null);
            }
            // Confidence for what the message actually is is low. Don't remove the message and let
            // system decide. Usually because it is not parsable it will be dropped.
            return false;
        } else {
        }
        String clientPrefix = settings.clientPrefix;
        WrappedMessageData messageData = VisualVoicemailSmsParser
            .parse(clientPrefix, messageBody);
        if (messageData != null) {
                sendVvmSmsBroadcast(context, vvmClientPackage, subId, messageData);
            sendVvmSmsBroadcast(context, vvmClientPackage, subId, messageData, null);
            return true;
        }

        buildPatternsMap(context);
        String mccMnc = telephonyManager.getSimOperator(subId);

        List<Pattern> patterns = sPatterns.get(mccMnc);
        if (patterns == null || patterns.isEmpty()) {
            return false;
        }

        for (Pattern pattern : patterns) {
            if (pattern.matcher(messageBody).matches()) {
                Log.w(TAG, "Incoming SMS matches pattern " + pattern + " but has illegal format, "
                    + "still dropping as VVM SMS");
                sendVvmSmsBroadcast(context, vvmClientPackage, subId, null, messageBody);
                return true;
            }
        }
        return false;
    }

    private static void buildPatternsMap(Context context) {
        if (sPatterns != null) {
            return;
        }
        sPatterns = new ArrayMap<>();
        // TODO(twyen): build from CarrierConfig once public API can be updated.
        for (String entry : context.getResources()
            .getStringArray(com.android.internal.R.array.config_vvmSmsFilterRegexes)) {
            String[] mccMncList = entry.split(";")[0].split(",");
            Pattern pattern = Pattern.compile(entry.split(";")[1]);

            for (String mccMnc : mccMncList) {
                if (!sPatterns.containsKey(mccMnc)) {
                    sPatterns.put(mccMnc, new ArrayList<>());
                }
                sPatterns.get(mccMnc).add(pattern);
            }
        }
    }

    private static void sendVvmSmsBroadcast(Context context, String vvmClientPackage, int subId,
        WrappedMessageData messageData) {
        @Nullable WrappedMessageData messageData, @Nullable String messageBody) {
        Log.i(TAG, "VVM SMS received");
        Intent intent = new Intent(VoicemailContract.ACTION_VOICEMAIL_SMS_RECEIVED);
        if (messageData != null) {
            intent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_PREFIX, messageData.prefix);
            intent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS, messageData.fields);
        }
        if (messageBody != null) {
            intent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_MESSAGE_BODY, messageBody);
        }
        intent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID, subId);
        intent.setPackage(vvmClientPackage);
        context.sendBroadcast(intent);
    }

    /**
     * @return the message body of the SMS, or {@code null} if it can not be parsed.
     */
    @Nullable
    private static String getFullMessage(byte[][] pdus, String format) {
        StringBuilder builder = new StringBuilder();
        for (byte pdu[] : pdus) {