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

Commit fb56fe36 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Set reject duplicates bit on SMS pdu for IMS fallback

When performing an IMS fallback to GSM, enable the TP-RD bit
on the outgoing PDU so that we do not accidently send duplicate
messages to the network.

Bug: 111314846
Test: atest FrameworksTelephonyTests:ImsSmsDispatcherTest
Change-Id: I91f2e6f3e74b2fbc5a87566a51d06e96962b3e28
parent 877bf6fd
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ import android.os.PersistableBundle;
import android.os.RemoteException;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.feature.ImsFeature;
@@ -29,8 +31,6 @@ import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.telephony.ims.stub.ImsSmsImplBase.SendStatusResult;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.util.Pair;

import com.android.ims.ImsException;
@@ -130,6 +130,7 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                    sendSms(tracker);
                    break;
                case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
                    tracker.mRetryCount += 1;
                    fallbackToPstn(token, tracker);
                    break;
                default:
@@ -229,7 +230,7 @@ public class ImsSmsDispatcher extends SMSDispatcher {
    private void setListeners() throws ImsException {
        getImsManager().addRegistrationCallback(mRegistrationCallback);
        getImsManager().addCapabilitiesCallback(mCapabilityCallback);
        getImsManager().setSmsListener(mImsSmsListener);
        getImsManager().setSmsListener(getSmsListener());
        getImsManager().onSmsReady();
    }

@@ -379,4 +380,9 @@ public class ImsSmsDispatcher extends SMSDispatcher {
    protected boolean isCdmaMo() {
        return mSmsDispatchersController.isCdmaFormat(getFormat());
    }

    @VisibleForTesting
    public IImsSmsListener getSmsListener() {
        return mImsSmsListener;
    }
}
+82 −13
Original line number Diff line number Diff line
@@ -17,24 +17,32 @@
package com.android.internal.telephony;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.os.HandlerThread;
import android.telephony.SmsMessage;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.test.suitebuilder.annotation.SmallTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import java.util.HashMap;

public class ImsSmsDispatcherTest extends TelephonyTest {
    @Mock private SmsDispatchersController mSmsDispatchersController;
    @Mock private SMSDispatcher.SmsTracker mSmsTracker;
    private HashMap<String, Object> mTrackerData;
    private ImsSmsDispatcher mImsSmsDispatcher;
    private ImsSmsDispatcherTestHandler mImsSmsDispatcherTestHandler;

@@ -48,6 +56,7 @@ public class ImsSmsDispatcherTest extends TelephonyTest {
        @Override
        public void onLooperPrepared() {
            mImsSmsDispatcher = spy(new ImsSmsDispatcher(mPhone, mSmsDispatchersController));
            when(mSmsDispatchersController.isIms()).thenReturn(true);
            setReady(true);
        }
    }
@@ -58,36 +67,96 @@ public class ImsSmsDispatcherTest extends TelephonyTest {

        mImsSmsDispatcherTestHandler = new ImsSmsDispatcherTestHandler(TAG);
        mImsSmsDispatcherTestHandler.start();

        mTrackerData = new HashMap(1);
        when(mSmsTracker.getData()).thenReturn(mTrackerData);
        waitUntilReady();
    }

    @Test @SmallTest
    public void testSendSms() {
    /**
     * Send an SMS and verify that the token and PDU is correct.
     */
    @Test
    @SmallTest
    public void testSendSms() throws Exception {
        int token = mImsSmsDispatcher.mNextToken.get();
        int trackersSize = mImsSmsDispatcher.mTrackers.size();

        byte[] pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(null,
                "+15555551212", "Test", false).encodedMessage;
        mTrackerData.put("pdu", pdu);
        when(mImsManager.getSmsFormat()).thenReturn(SmsMessage.FORMAT_3GPP);
        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);

        //Send an SMS
        mImsSmsDispatcher.sendSms(mSmsTracker);

        assertEquals(token + 1, mImsSmsDispatcher.mNextToken.get());
        assertEquals(trackersSize + 1, mImsSmsDispatcher.mTrackers.size());
        ArgumentCaptor<byte[]> byteCaptor = ArgumentCaptor.forClass(byte[].class);
        verify(mImsManager).sendSms(eq(token + 1), anyInt(), eq(SmsMessage.FORMAT_3GPP),
                nullable(String.class), eq(false), eq(pdu));
    }

    @Test @SmallTest
    public void testFallbackToPstn() {
        int token = 0;
    /**
     * Ensure that when sending a GSM text fails with SEND_STATUS_ERROR_FALLBACK, retry with
     * a non-zero retry count (set TP-RD).
     */
    @Test
    @SmallTest
    public void testFallbackGsmRetry() throws Exception {
        int token = mImsSmsDispatcher.mNextToken.get();
        mTrackerData.put("pdu", com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(null,
                "+15555551212", "Test", false).encodedMessage);
        mImsSmsDispatcher.mTrackers.put(token, mSmsTracker);
        doNothing().when(mSmsDispatchersController).sendRetrySms(mSmsTracker);
        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);

        mImsSmsDispatcher.fallbackToPstn(token, mSmsTracker);
        // Fallback over GSM
        mImsSmsDispatcher.getSmsListener().onSendSmsResult(token, 0,
                ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK, 0);
        ArgumentCaptor<SMSDispatcher.SmsTracker> captor =
                ArgumentCaptor.forClass(SMSDispatcher.SmsTracker.class);
        // Ensure GsmSmsDispatcher calls sendSms
        verify(mSmsDispatchersController).sendRetrySms(captor.capture());

        verify(mSmsDispatchersController).sendRetrySms(mSmsTracker);
        assertNull(mImsSmsDispatcher.mTrackers.get(token));
        assertNotNull(captor.getValue());
        assertTrue(captor.getValue().mRetryCount > 0);

    }

    /**
     * Ensure that when an outgoing SMS has failed over IMS with SEND_STATUS_ERROR_RETRY, it is
     * sent over the IMS channel again with the TP-RD bit set.
     */
    @Test
    @SmallTest
    public void testErrorImsRetry() throws Exception {
        int token = mImsSmsDispatcher.mNextToken.get();
        mTrackerData.put("pdu", com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(null,
                "+15555551212", "Test", false).encodedMessage);
        when(mImsManager.getSmsFormat()).thenReturn(SmsMessage.FORMAT_3GPP);
        mImsSmsDispatcher.mTrackers.put(token, mSmsTracker);
        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);

        // Fallback over GSM
        mImsSmsDispatcher.getSmsListener().onSendSmsResult(token, 0,
                ImsSmsImplBase.SEND_STATUS_ERROR_RETRY, 0);

        // Make sure retry bit set
        ArgumentCaptor<byte[]> byteCaptor = ArgumentCaptor.forClass(byte[].class);
        verify(mImsManager).sendSms(eq(token + 1), anyInt(), nullable(String.class),
                nullable(String.class), eq(true), byteCaptor.capture());
        byte[] pdu = byteCaptor.getValue();
        // Make sure that TP-RD is set for this message
        assertNotNull(pdu);
        assertEquals(0x04, (pdu[0] & 0x04));
    }

    @After
    public void tearDown() throws Exception {
        mImsSmsDispatcher = null;
        mImsSmsDispatcherTestHandler.quit();
        mImsSmsDispatcherTestHandler.join();
        super.tearDown();
    }
}