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

Commit acd4ebaa authored by Sal Savage's avatar Sal Savage
Browse files

Drop messages with handles we didn't ask for

Problem: The typical message download process has us request the
contents for a specific message handle. Its possible that the remote
device can send back a message object with a handle we didn't recognize.
When this happens, the metadata for that message doesn't exist in our
map, which was causing an NPE.

Solution: Check that the handle exists in our map and don't use a null
object.

Flag: EXEMPT, simple null check with added test coverage
Bug: 373632001
Test: atest com.android.bluetooth.mapclient
Change-Id: I5a2efe865ce2fdbcd428b9c5d1eaedcbee0ff1bd
parent 811f3370
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -1086,15 +1086,21 @@ class MceStateMachine extends StateMachine {
            if (message == null) {
                return;
            }

            MessageMetadata metadata = mMessages.get(request.getHandle());
            if (metadata == null) {
                Log.e(TAG, "No request record of received message, handle=" + request.getHandle());
                return;
            }

            mDatabase.storeMessage(
                    message,
                    request.getHandle(),
                    mMessages.get(request.getHandle()).getTimestamp(),
                    mMessages.get(request.getHandle()).getSeen());
                    message, request.getHandle(), metadata.getTimestamp(), metadata.getSeen());

            if (!INBOX_PATH.equalsIgnoreCase(message.getFolder())) {
                Log.d(TAG, "Ignoring message received in " + message.getFolder() + ".");
                return;
            }

            switch (message.getType()) {
                case SMS_CDMA:
                case SMS_GSM:
@@ -1104,7 +1110,6 @@ class MceStateMachine extends StateMachine {
                    Log.d(TAG, "Recipients" + message.getRecipients().toString());

                    // Grab the message metadata and update the cached read status from the bMessage
                    MessageMetadata metadata = mMessages.get(request.getHandle());
                    metadata.setRead(request.getMessage().getStatus() == Bmessage.Status.READ);

                    Intent intent = new Intent();
+43 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ public class MapClientStateMachineTest {
    private Bmessage mTestIncomingMmsBmessage;
    private String mTestMessageSmsHandle = "0001";
    private String mTestMessageMmsHandle = "0002";
    private String mTestMessageUnknownHandle = "0003";
    boolean mIsAdapterServiceSet;
    boolean mIsMapClientServiceStarted;

@@ -721,6 +722,48 @@ public class MapClientStateMachineTest {
                        eq(MESSAGE_NOT_SEEN));
    }

    @Test
    public void testReceiveNewMessage_handleNotRecognized_messageDropped() {
        setupSdpRecordReceipt();
        Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED);
        mMceStateMachine.sendMessage(msg);

        // verifying that state machine is in the Connected state
        assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED);

        // Send new message event with handle A
        String dateTime = new ObexTime(Instant.now()).toString();
        EventReport event =
                createNewEventReport(
                        "NewMessage",
                        dateTime,
                        mTestMessageMmsHandle,
                        "telecom/msg/inbox",
                        null,
                        "MMS");

        // Prepare to send back message content, but use handle B
        when(mMockRequestGetMessage.getHandle()).thenReturn(mTestMessageUnknownHandle);
        when(mMockRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage);

        mMceStateMachine.receiveEvent(event);

        TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper());
        verify(mMockMasClient).makeRequest(any(RequestGetMessage.class));

        msg =
                Message.obtain(
                        mHandler,
                        MceStateMachine.MSG_MAS_REQUEST_COMPLETED,
                        mMockRequestGetMessage);
        mMceStateMachine.sendMessage(msg);

        // We should drop the message and not store it, as it's not one we requested
        TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper());
        verify(mMockDatabase, never())
                .storeMessage(any(Bmessage.class), anyString(), anyLong(), anyBoolean());
    }

    /** Test seen status set in database on initial download */
    @Test
    public void testDownloadExistingSms_messageStoredAsSeen() {