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

Commit 6b247f3a authored by Sal Savage's avatar Sal Savage Committed by Android (Google) Code Review
Browse files

Merge "Add timestamp and read status extras to MAP Client message broadcasts" into qt-dev

parents 16bc4e20 b3c5570d
Loading
Loading
Loading
Loading
+102 −6
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.bluetooth.SdpMasRecord;
import android.content.Intent;
import android.net.Uri;
import android.os.Message;
import android.provider.Telephony;
import android.telecom.PhoneAccount;
import android.telephony.SmsManager;
import android.util.Log;
@@ -68,8 +69,10 @@ import com.android.vcard.VCardProperty;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/* The MceStateMachine is responsible for setting up and maintaining a connection to a single
 * specific Messaging Server Equipment endpoint.  Upon connect command an SDP record is retrieved,
@@ -122,6 +125,48 @@ final class MceStateMachine extends StateMachine {
            new HashMap<>(MAX_MESSAGES);
    private Bmessage.Type mDefaultMessageType = Bmessage.Type.SMS_CDMA;

    /**
     * An object to hold the necessary meta-data for each message so we can broadcast it alongside
     * the message content.
     *
     * This is necessary because the metadata is inferred or received separately from the actual
     * message content.
     *
     * 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 {
        private final String mHandle;
        private final Long mTimestamp;
        private boolean mRead;

        MessageMetadata(String handle, Long timestamp, boolean read) {
            mHandle = handle;
            mTimestamp = timestamp;
            mRead = read;
        }

        public String getHandle() {
            return mHandle;
        }

        public Long getTimestamp() {
            return mTimestamp;
        }

        public synchronized boolean getRead() {
            return mRead;
        }

        public synchronized void setRead(boolean read) {
            mRead = read;
        }
    }

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

    MceStateMachine(MapClientService service, BluetoothDevice device) {
        this(service, device, null);
    }
@@ -503,6 +548,15 @@ final class MceStateMachine extends StateMachine {
            mPreviousState = BluetoothProfile.STATE_CONNECTED;
        }

        /**
         * Given a message notification event, will ensure message caching and updating and update
         * interested applications.
         *
         * Message notifications arrive for both remote message reception and Message-Listing object
         * updates that are triggered by the server side.
         *
         * @param msg - A Message object containing a EventReport object describing the remote event
         */
        private void processNotification(Message msg) {
            if (DBG) {
                Log.d(TAG, "Handler: msg: " + msg.what);
@@ -518,7 +572,14 @@ final class MceStateMachine extends StateMachine {
                    switch (ev.getType()) {

                        case NEW_MESSAGE:
                            //mService.get().sendNewMessageNotification(ev);
                            // 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();
                                MessageMetadata metadata = new MessageMetadata(ev.getHandle(),
                                        calendar.getTime().getTime(), false);
                                mMessages.put(ev.getHandle(), metadata);
                            }
                            mMasClient.makeRequest(new RequestGetMessage(ev.getHandle(),
                                    MasClient.CharsetType.UTF_8, false));
                            break;
@@ -534,6 +595,8 @@ final class MceStateMachine extends StateMachine {
        // Sets the specified message status to "read" (from "unread" status, mostly)
        private void markMessageRead(RequestGetMessage request) {
            if (DBG) Log.d(TAG, "markMessageRead");
            MessageMetadata metadata = mMessages.get(request.getHandle());
            metadata.setRead(true);
            mMasClient.makeRequest(new RequestSetMessageStatus(
                    request.getHandle(), RequestSetMessageStatus.StatusIndicator.READ));
        }
@@ -545,21 +608,41 @@ final class MceStateMachine extends StateMachine {
                    request.getHandle(), RequestSetMessageStatus.StatusIndicator.DELETED));
        }

        /**
         * Given the result of a Message Listing request, will cache the contents of each Message in
         * the Message Listing Object and kick off requests to retrieve message contents from the
         * remote device.
         *
         * @param request - A request object that has been resolved and returned with a message list
         */
        private void processMessageListing(RequestGetMessagesListing request) {
            if (DBG) {
                Log.d(TAG, "processMessageListing");
            }
            ArrayList<com.android.bluetooth.mapclient.Message> messageHandles = request.getList();
            if (messageHandles != null) {
                for (com.android.bluetooth.mapclient.Message handle : messageHandles) {
            ArrayList<com.android.bluetooth.mapclient.Message> messageListing = request.getList();
            if (messageListing != null) {
                for (com.android.bluetooth.mapclient.Message msg : messageListing) {
                    if (DBG) {
                        Log.d(TAG, "getting message ");
                    }
                    getMessage(handle.getHandle());
                    // A message listing coming from the server should always have up to date data
                    mMessages.put(msg.getHandle(), new MessageMetadata(msg.getHandle(),
                            msg.getDateTime().getTime(), msg.isRead()));
                    getMessage(msg.getHandle());
                }
            }
        }

        /**
         * Given the response of a GetMessage request, will broadcast the bMessage contents on to
         * all registered applications.
         *
         * Inbound messages arrive as bMessage objects following a GetMessage request. GetMessage
         * uses a message handle that can arrive from both a GetMessageListing request or a Message
         * Notification event.
         *
         * @param request - A request object that has been resolved and returned with message data
         */
        private void processInboundMessage(RequestGetMessage request) {
            Bmessage message = request.getMessage();
            if (DBG) {
@@ -588,10 +671,18 @@ final 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();
                    intent.setAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
                    intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
                    intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE, request.getHandle());
                    intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_TIMESTAMP,
                            metadata.getTimestamp());
                    intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_READ_STATUS,
                            metadata.getRead());
                    intent.putExtra(android.content.Intent.EXTRA_TEXT, message.getBodyContent());
                    VCardEntry originator = message.getOriginator();
                    if (originator != null) {
@@ -610,7 +701,12 @@ final class MceStateMachine extends StateMachine {
                        intent.putExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_NAME,
                                originator.getDisplayName());
                    }
                    mService.sendBroadcast(intent);
                    // Only send to the current default SMS app if one exists
                    String defaultMessagingPackage = Telephony.Sms.getDefaultSmsPackage(mService);
                    if (defaultMessagingPackage != null) {
                        intent.setPackage(defaultMessagingPackage);
                    }
                    mService.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
                    break;

                case MMS: