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

Commit 4cd29980 authored by Dikra Prasetya's avatar Dikra Prasetya Committed by William Escande
Browse files

Support Event 1.1 with Datetime field.

Bug: 266796373
Bug: 271386921
Tag: #feature
Test: atest BluetoothInstrumentationTests
(cherry picked from https://android-review.googlesource.com/q/commit:270565b07dbc3c86b2b8a14f94e37d2bcea3080a)
Merged-In: Ic8c66f8db004ff8245f139e9047091e2bf52657a
Bug: 263323082

Change-Id: I24d3293aa79387b5e0df1509d514c9cbbce57cde
parent a2e7dc9c
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.vcard.VCardConstants;
import com.android.vcard.VCardEntry;
import com.android.vcard.VCardProperty;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -152,7 +153,8 @@ class MceStateMachine extends StateMachine {
     * Note: In the future it may be best to use the entries from the MessageListing in full instead
     * of this small subset.
     */
    private class MessageMetadata {
    @VisibleForTesting
    static class MessageMetadata {
        private final String mHandle;
        private final Long mTimestamp;
        private boolean mRead;
@@ -181,7 +183,8 @@ class MceStateMachine extends StateMachine {
    }

    // Map each message to its metadata via the handle
    private ConcurrentHashMap<String, MessageMetadata> mMessages =
    @VisibleForTesting
    ConcurrentHashMap<String, MessageMetadata> mMessages =
            new ConcurrentHashMap<String, MessageMetadata>();

    MceStateMachine(MapClientService service, BluetoothDevice device) {
@@ -689,12 +692,15 @@ class MceStateMachine extends StateMachine {
                    }
                    switch (ev.getType()) {
                        case NEW_MESSAGE:
                            // Infer the timestamp for this message as 'now' and read status false
                            // instead of getting the message listing data for it
                            if (!mMessages.contains(ev.getHandle())) {
                                Calendar calendar = Calendar.getInstance();
                            if (!mMessages.containsKey(ev.getHandle())) {
                                Long timestamp = ev.getTimestamp();
                                if (timestamp == null) {
                                    // Infer the timestamp for this message as 'now' and read status
                                    // false instead of getting the message listing data for it
                                    timestamp = new Long(Instant.now().toEpochMilli());
                                }
                                MessageMetadata metadata = new MessageMetadata(ev.getHandle(),
                                        calendar.getTime().getTime(), false);
                                        timestamp, false);
                                mMessages.put(ev.getHandle(), metadata);
                            }
                            mMasClient.makeRequest(new RequestGetMessage(ev.getHandle(),
+35 −1
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.bluetooth.mapclient;

import android.annotation.Nullable;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
@@ -38,12 +41,14 @@ import java.util.HashMap;
public class EventReport {
    private static final String TAG = "EventReport";
    private final Type mType;
    private final String mDateTime;
    private final String mHandle;
    private final String mFolder;
    private final String mOldFolder;
    private final Bmessage.Type mMsgType;

    private EventReport(HashMap<String, String> attrs) throws IllegalArgumentException {
    @VisibleForTesting
    EventReport(HashMap<String, String> attrs) throws IllegalArgumentException {
        mType = parseType(attrs.get("type"));

        if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
@@ -64,6 +69,8 @@ public class EventReport {

        mOldFolder = attrs.get("old_folder");

        mDateTime = attrs.get("datetime");

        if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
            String s = attrs.get("msg_type");

@@ -180,12 +187,39 @@ public class EventReport {
        return mMsgType;
    }

    /**
     * @return value corresponding to <code>datetime</code> parameter in MAP
     * specification for NEW_MESSAGE (can be null)
     */
    @Nullable
    public String getDateTime() {
        return mDateTime;
    }

    /**
     * @return timestamp from the value corresponding to <code>datetime</code> parameter in MAP
     * specification for NEW_MESSAGE (can be null)
     */
    @Nullable
    public Long getTimestamp() {
        if (mDateTime != null) {
            ObexTime obexTime = new ObexTime(mDateTime);
            if (obexTime != null) {
                return obexTime.getInstant().toEpochMilli();
            }
        }
        return null;
    }

    @Override
    public String toString() {
        JSONObject json = new JSONObject();

        try {
            json.put("type", mType);
            if (mDateTime != null) {
                json.put("datetime", mDateTime);
            }
            json.put("handle", mHandle);
            json.put("folder", mFolder);
            json.put("old_folder", mOldFolder);
+35 −0
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ public class EventReportTest {
        EventReport report = EventReport.fromStream(new DataInputStream(stream));

        assertThat(report.getType()).isEqualTo(type);
        assertThat(report.getDateTime()).isNull();
        assertThat(report.getTimestamp()).isNull();
        assertThat(report.getHandle()).isEqualTo(handle);
        assertThat(report.getFolder()).isEqualTo(folder);
        assertThat(report.getOldFolder()).isEqualTo(oldFolder);
@@ -76,6 +78,39 @@ public class EventReportTest {
        assertThat(report).isNull();
    }

    @Test
    public void fromStreamWithDateTime() throws Exception {
        EventReport.Type type = EventReport.Type.PARTICIPANT_CHAT_STATE_CHANGED;
        String handle = "FFAB";
        String dateTime = "20190101T121314";
        String folder = "test_folder";
        String oldFolder = "old_folder";
        Bmessage.Type msgType = Bmessage.Type.MMS;

        final StringBuilder xml = new StringBuilder();
        xml.append("<event\n");
        xml.append("type=\"" + type.toString() + "\"\n");
        xml.append("datetime=\"" + dateTime + "\"\n");
        xml.append("handle=\"" + handle + "\"\n");
        xml.append("folder=\"" + folder + "\"\n");
        xml.append("old_folder=\"" + oldFolder + "\"\n");
        xml.append("msg_type=\"" + msgType + "\"\n");
        xml.append("/>\n");
        ByteArrayInputStream stream = new ByteArrayInputStream(xml.toString().getBytes());

        EventReport report = EventReport.fromStream(new DataInputStream(stream));

        assertThat(report.getType()).isEqualTo(type);
        assertThat(report.getDateTime()).isEqualTo(dateTime);
        assertThat(report.getTimestamp()).isEqualTo(
                new ObexTime(dateTime).getInstant().toEpochMilli());
        assertThat(report.getHandle()).isEqualTo(handle);
        assertThat(report.getFolder()).isEqualTo(folder);
        assertThat(report.getOldFolder()).isEqualTo(oldFolder);
        assertThat(report.getMsgType()).isEqualTo(msgType);
        assertThat(report.toString()).isNotEmpty();
    }

    @Test
    public void fromStream_withIOException_doesNotCrash_andReturnNull() throws Exception {
        InputStream stream = mock(InputStream.class);
+60 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.bluetooth.mapclient;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.*;

import android.app.BroadcastOptions;
@@ -65,6 +67,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

@@ -77,6 +80,9 @@ public class MapClientStateMachineTest {

    private static final int ASYNC_CALL_TIMEOUT_MILLIS = 100;
    private static final int DISCONNECT_TIMEOUT = 3000;

    private String mTestMessageSmsHandle = "0001";

    @Rule
    public final ServiceTestRule mServiceRule = new ServiceTestRule();
    private BluetoothAdapter mAdapter;
@@ -417,6 +423,43 @@ public class MapClientStateMachineTest {
        Assert.assertEquals(1, mMockContentProvider.mInsertOperationCount);
    }

    /**
     * Test receiving a new message notification.
     */
    @Test
    public void testReceiveNewMessageNotification() {
        setupSdpRecordReceipt();
        Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED);
        mMceStateMachine.sendMessage(msg);

        verify(mMockMapClientService,
                timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)).sendBroadcastMultiplePermissions(
                mIntentArgument.capture(), any(String[].class),
                any(BroadcastOptions.class));
        assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);

        // Receive a new message notification.
        String dateTime = new ObexTime(Instant.now()).toString();
        EventReport event = createNewEventReport("NewMessage", dateTime, mTestMessageSmsHandle,
                "telecom/msg/inbox", null, "SMS_GSM");

        Message notificationMessage =
                Message.obtain(mHandler, MceStateMachine.MSG_NOTIFICATION, (Object)event);

        mMceStateMachine.getCurrentState().processMessage(notificationMessage);

        verify(mMockMasClient,
                timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1))
                        .makeRequest(any(RequestGetMessage.class));

        MceStateMachine.MessageMetadata messageMetadata =
                mMceStateMachine.mMessages.get(mTestMessageSmsHandle);
        Assert.assertEquals(messageMetadata.getHandle(), mTestMessageSmsHandle);
        Assert.assertEquals(
                new ObexTime(Instant.ofEpochMilli(messageMetadata.getTimestamp())).toString(),
                dateTime);
    }

    private void setupSdpRecordReceipt() {
        // Perform first part of MAP connection logic.
        verify(mMockMapClientService,
@@ -460,4 +503,21 @@ public class MapClientStateMachineTest {
        }
    }

    EventReport createNewEventReport(String mType, String mDateTime, String mHandle, String mFolder,
            String mOldFolder, String mMsgType){

        HashMap<String, String> attrs = new HashMap<String, String>();

        attrs.put("type", mType);
        attrs.put("datetime", mDateTime);
        attrs.put("handle", mHandle);
        attrs.put("folder", mFolder);
        attrs.put("old_folder", mOldFolder);
        attrs.put("msg_type", mMsgType);

        EventReport event = new EventReport(attrs);

        return event;

    }
}