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

Commit 030c8877 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Invoke SMS filters for messages from blocked numbers." into rvc-qpr-dev

parents 83b3cdf5 407ead5b
Loading
Loading
Loading
Loading
+96 −43
Original line number Diff line number Diff line
@@ -1057,6 +1057,15 @@ public abstract class InboundSmsHandler extends StateMachine {
            }
        }

        // Always invoke SMS filters, even if the number ends up being blocked, to prevent
        // surprising bugs due to blocking numbers that happen to be used for visual voicemail SMS
        // or other carrier system messages.
        boolean filterInvoked = filterSms(
                pdus, destPort, tracker, resultReceiver, true /* userUnlocked */, block);

        if (!filterInvoked) {
            // Block now if the filter wasn't invoked. Otherwise, it will be the responsibility of
            // the filter to delete the SMS once processing completes.
            if (block) {
                deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
                        DELETE_PERMANENTLY);
@@ -1065,10 +1074,6 @@ public abstract class InboundSmsHandler extends StateMachine {
                return false;
            }

        boolean filterInvoked = filterSms(
            pdus, destPort, tracker, resultReceiver, true /* userUnlocked */);

        if (!filterInvoked) {
            dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver,
                    tracker.isClass0(), tracker.getSubId(), tracker.getMessageId());
        }
@@ -1094,7 +1099,8 @@ public abstract class InboundSmsHandler extends StateMachine {
        if (destPort == -1) {
            // This is a regular SMS - hand it to the carrier or system app for filtering.
            boolean filterInvoked = filterSms(
                pdus, destPort, tracker, resultReceiver, false /* userUnlocked */);
                    pdus, destPort, tracker, resultReceiver, false /* userUnlocked */,
                    false /* block */);
            if (filterInvoked) {
                // filter invoked, wait for it to return the result.
                return true;
@@ -1153,13 +1159,14 @@ public abstract class InboundSmsHandler extends StateMachine {
    private List<SmsFilter> createDefaultSmsFilters() {
        List<SmsFilter> smsFilters = new ArrayList<>(3);
        smsFilters.add(
                (pdus, destPort, tracker, resultReceiver, userUnlocked, remainingFilters) -> {
                (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters)
                        -> {
                    CarrierServicesSmsFilterCallback filterCallback =
                            new CarrierServicesSmsFilterCallback(
                                    pdus, destPort, tracker, tracker.getFormat(), resultReceiver,
                                    userUnlocked,
                                    tracker.isClass0(), tracker.getSubId(), tracker.getMessageId(),
                                    remainingFilters);
                                    block, remainingFilters);
                    CarrierServicesSmsFilter carrierServicesFilter = new CarrierServicesSmsFilter(
                            mContext, mPhone, pdus, destPort, tracker.getFormat(),
                            filterCallback, getName() + "::CarrierServicesSmsFilter",
@@ -1172,23 +1179,25 @@ public abstract class InboundSmsHandler extends StateMachine {
                    }
                });
        smsFilters.add(
                (pdus, destPort, tracker, resultReceiver, userUnlocked, remainingFilters) -> {
                (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters)
                        -> {
                    if (VisualVoicemailSmsFilter.filter(
                            mContext, pdus, tracker.getFormat(), destPort, tracker.getSubId())) {
                        logWithLocalLog("Visual voicemail SMS dropped", tracker.getMessageId());
                        dropSms(resultReceiver);
                        dropFilteredSms(tracker, resultReceiver, block);
                        return true;
                    }
                    return false;
                });
        smsFilters.add(
                (pdus, destPort, tracker, resultReceiver, userUnlocked, remainingFilters) -> {
                (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters)
                        -> {
                    MissedIncomingCallSmsFilter missedIncomingCallSmsFilter =
                            new MissedIncomingCallSmsFilter(mPhone);
                    if (missedIncomingCallSmsFilter.filter(pdus, tracker.getFormat())) {
                        logWithLocalLog("Missed incoming call SMS received",
                                tracker.getMessageId());
                        dropSms(resultReceiver);
                        dropFilteredSms(tracker, resultReceiver, block);
                        return true;
                    }
                    return false;
@@ -1196,6 +1205,18 @@ public abstract class InboundSmsHandler extends StateMachine {
        return smsFilters;
    }

    private void dropFilteredSms(
            InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean block) {
        if (block) {
            deleteFromRawTable(
                    tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
                    DELETE_PERMANENTLY);
            sendMessage(EVENT_BROADCAST_COMPLETE);
        } else {
            dropSms(resultReceiver);
        }
    }

    /**
     * Filters the SMS.
     *
@@ -1205,17 +1226,18 @@ public abstract class InboundSmsHandler extends StateMachine {
     * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise.
     */
    private boolean filterSms(byte[][] pdus, int destPort,
            InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked) {
        return filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, mSmsFilters);
            InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked,
            boolean block) {
        return filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, mSmsFilters);
    }

    private static boolean filterSms(byte[][] pdus, int destPort,
            InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked,
            List<SmsFilter> filters) {
            boolean block, List<SmsFilter> filters) {
        ListIterator<SmsFilter> iterator = filters.listIterator();
        while (iterator.hasNext()) {
            SmsFilter smsFilter = iterator.next();
            if (smsFilter.filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked,
            if (smsFilter.filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block,
                    filters.subList(iterator.nextIndex(), filters.size()))) {
                return true;
            }
@@ -1657,11 +1679,13 @@ public abstract class InboundSmsHandler extends StateMachine {
        private final boolean mIsClass0;
        private final int mSubId;
        private final long mMessageId;
        private final boolean mBlock;
        private final List<SmsFilter> mRemainingFilters;

        CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, InboundSmsTracker tracker,
                String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked,
                boolean isClass0, int subId, long messageId, List<SmsFilter> remainingFilters) {
                boolean isClass0, int subId, long messageId, boolean block,
                List<SmsFilter> remainingFilters) {
            mPdus = pdus;
            mDestPort = destPort;
            mTracker = tracker;
@@ -1671,19 +1695,41 @@ public abstract class InboundSmsHandler extends StateMachine {
            mIsClass0 = isClass0;
            mSubId = subId;
            mMessageId = messageId;
            mBlock = block;
            mRemainingFilters = remainingFilters;
        }

        @Override
        public void onFilterComplete(int result) {
            log("onFilterComplete: result is " + result, mMessageId);
            if ((result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) == 0) {
                // Message isn't dropped, so run it through the remaining filters.
                if (filterSms(mPdus, mDestPort, mTracker, mSmsBroadcastReceiver, mUserUnlocked,
                        mRemainingFilters)) {

            boolean carrierRequestedDrop =
                    (result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) != 0;
            if (carrierRequestedDrop) {
                // Carrier app asked the platform to drop the SMS. Drop it from the database and
                // complete processing.
                dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock);
                return;
            }

            boolean filterInvoked = filterSms(mPdus, mDestPort, mTracker, mSmsBroadcastReceiver,
                    mUserUnlocked, mBlock, mRemainingFilters);
            if (filterInvoked) {
                // A remaining filter has assumed responsibility for further message processing.
                return;
            }

            // Now that all filters have been invoked, drop the message if it is blocked.
            // TODO(b/156910035): Remove mUserUnlocked once we stop showing the new message
            // notification for blocked numbers.
            if (mUserUnlocked && mBlock) {
                log("onFilterComplete: dropping message as the sender is blocked",
                        mTracker.getMessageId());
                dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock);
                return;
            }

            // Message matched no filters and is not blocked, so complete processing.
            if (mUserUnlocked) {
                dispatchSmsDeliveryIntent(
                        mPdus, mSmsFormat, mDestPort, mSmsBroadcastReceiver, mIsClass0, mSubId,
@@ -1697,10 +1743,6 @@ public abstract class InboundSmsHandler extends StateMachine {
                }
                sendMessage(EVENT_BROADCAST_COMPLETE);
            }
            } else {
                // Drop this SMS.
                dropSms(mSmsBroadcastReceiver);
            }
        }
    }

@@ -2025,9 +2067,20 @@ public abstract class InboundSmsHandler extends StateMachine {
        /**
         * Returns true if a filter is invoked and the SMS processing flow should be diverted, false
         * otherwise.
         *
         * <p>If the filter can immediately determine that the message matches, it must call
         * {@link #dropFilteredSms} to drop the message from the database once it has been
         * processed.
         *
         * <p>If the filter must perform some asynchronous work to determine if the message matches,
         * it should return true to defer processing. Once it has made a determination, if it finds
         * the message matches, it must call {@link #dropFilteredSms}. If the message does not
         * match, it must be passed through {@code remainingFilters} and either dropped if the
         * remaining filters all return false or if {@code block} is true, or else it must be
         * broadcast.
         */
        boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker,
                SmsBroadcastReceiver resultReceiver, boolean userUnlocked,
                SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block,
                List<SmsFilter> remainingFilters);
    }
}
+16 −16
Original line number Diff line number Diff line
@@ -374,9 +374,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        verify(mContext, never()).sendBroadcast(any(Intent.class));
        assertEquals("IdleState", getCurrentState().getName());

        // verify no filter was invoked.
        // TODO(b/136262737): Adjust test once blocked SMSes are passed through filters too.
        verifySmsFiltersInvoked(never());
        // Filter should still be invoked.
        verifySmsFiltersInvoked(times(1));
    }

    @Test
@@ -385,7 +384,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // Configure the first filter to drop the SMS.
        when(mSmsFilter.filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any()))
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any()))
                .thenAnswer((Answer<Boolean>) invocation -> {
                    mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_COMPLETE);
                    return true;
@@ -401,7 +400,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // verify second filter was never invoked.
        verify(mSmsFilter2, never()).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
    }

    @Test
@@ -410,7 +409,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // Have the first filter indicate it matched without completing the flow.
        when(mSmsFilter.filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any())).thenReturn(true);
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any()))
                .thenReturn(true);

        transitionFromStartupToIdle();

@@ -423,12 +423,12 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // Verify the first filter was invoked with the right set of remaining filters.
        verify(mSmsFilter).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), eq(Collections.singletonList(mSmsFilter2)));
                anyBoolean(), anyBoolean(), eq(Collections.singletonList(mSmsFilter2)));

        // Verify second filter was never invoked.
        verify(mSmsFilter2, never()).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());

        // Clean up by completing the broadcast, as an asynchronous filter must do.
        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_COMPLETE);
@@ -862,8 +862,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {

        verify(mContext, never()).sendBroadcast(any(Intent.class));
        assertEquals("IdleState", getCurrentState().getName());
        // TODO(b/136262737): Adjust test once blocked SMSes are passed through filters too.
        verifySmsFiltersInvoked(never());
        // Filter should still be invoked.
        verifySmsFiltersInvoked(times(1));
    }

    @Test
@@ -914,8 +914,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {

        verify(mContext, never()).sendBroadcast(any(Intent.class));
        assertEquals("IdleState", getCurrentState().getName());
        // TODO(b/136262737): Adjust test once blocked SMSes are passed through filters too.
        verifySmsFiltersInvoked(never());
        // Filter should still be invoked.
        verifySmsFiltersInvoked(times(1));
    }

    @Test
@@ -924,7 +924,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // Configure the first filter to drop the SMS.
        when(mSmsFilter.filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any()))
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any()))
                .thenAnswer((Answer<Boolean>) invocation -> {
                    mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_COMPLETE);
                    return true;
@@ -962,7 +962,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        // verify second filter was never invoked.
        verify(mSmsFilter2, never()).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
    }

    @Test
@@ -1114,9 +1114,9 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
    private void verifySmsFiltersInvoked(VerificationMode verificationMode) {
        verify(mSmsFilter, verificationMode).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
        verify(mSmsFilter2, verificationMode).filterSms(any(byte[][].class), anyInt(),
                any(InboundSmsTracker.class), any(InboundSmsHandler.SmsBroadcastReceiver.class),
                anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
                anyBoolean(), anyBoolean(), Mockito.<List<InboundSmsHandler.SmsFilter>>any());
    }
}