diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-08-15 04:38:47 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-08-15 04:38:47 +0000 |
commit | e0a300a31778bce16dba12aa1e7fa4ad9d0fa2bd (patch) | |
tree | e9632dee869aea8afb85a6ab456d570ad43b867b | |
parent | a10890b1177b8472ab4c2ae84cb7dcfefbe16a37 (diff) | |
parent | 4a6a99f1710792ee2fb04884b0ba4f399789cec4 (diff) | |
download | Messenger-android10-mainline-a-release.tar.gz |
Snap for 5803298 from 4a6a99f1710792ee2fb04884b0ba4f399789cec4 to qt-aml-releaseandroid-mainline-10.0.0_r2android10-mainline-a-release
Change-Id: Ia7920381bf673788922fe50e0e1b9ebfca4cda30
-rw-r--r-- | res/values/config.xml | 3 | ||||
-rw-r--r-- | src/com/android/car/messenger/MapMessage.java | 25 | ||||
-rw-r--r-- | src/com/android/car/messenger/MessengerDelegate.java | 106 | ||||
-rw-r--r-- | src/com/android/car/messenger/SmsDatabaseHandler.java | 2 | ||||
-rw-r--r-- | src/com/android/car/messenger/bluetooth/BluetoothMonitor.java | 13 | ||||
-rw-r--r-- | tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java | 28 |
6 files changed, 124 insertions, 53 deletions
diff --git a/res/values/config.xml b/res/values/config.xml index 56cb667..0696f07 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -18,4 +18,7 @@ <!-- Whether existing messages should be loaded. Recommended to turn off if head-unit's and BT-paired phone's clocks are not synced.--> <bool name="config_loadExistingMessages">false</bool> + <!-- Whether app should attempt to reconnect to Bluetooth MAP profile, once MAP is + disconnected. --> + <bool name="config_reconnectToMap">true</bool> </resources> diff --git a/src/com/android/car/messenger/MapMessage.java b/src/com/android/car/messenger/MapMessage.java index 4eee956..b4b7aee 100644 --- a/src/com/android/car/messenger/MapMessage.java +++ b/src/com/android/car/messenger/MapMessage.java @@ -33,7 +33,8 @@ class MapMessage { private String mSenderContactUri; private String mMessageText; private long mReceiveTime; - private boolean mIsRead; + private boolean mIsReadOnPhone; + private boolean mIsReadOnCar; /** * Constructs a {@link MapMessage} from {@code intent} that was received from MAP service via @@ -99,7 +100,7 @@ class MapMessage { mSenderContactUri = senderContactUri; mSenderName = senderName; mReceiveTime = receiveTime; - mIsRead = isRead; + mIsReadOnPhone = isRead; } /** @@ -151,14 +152,21 @@ class MapMessage { } public void markMessageAsRead() { - mIsRead = true; + mIsReadOnCar = true; } /** - * Returns the read status of the message. + * Returns {@code true} if message was read on the phone before it was received on the car. */ - public boolean isRead() { - return mIsRead; + public boolean isReadOnPhone() { + return mIsReadOnPhone; + } + + /** + * Returns {@code true} if message was read on the car. + */ + public boolean isReadOnCar() { + return mIsReadOnCar; } @Override @@ -169,8 +177,9 @@ class MapMessage { ", mMessageText='" + mMessageText + '\'' + ", mSenderContactUri='" + mSenderContactUri + '\'' + ", mSenderName='" + mSenderName + '\'' + - ", mReceiveTime=" + mReceiveTime + - ", mIsRead= " + mIsRead + + ", mReceiveTime=" + mReceiveTime + '\'' + + ", mIsReadOnPhone= " + mIsReadOnPhone + '\'' + + ", mIsReadOnCar= " + mIsReadOnCar + "}"; } } diff --git a/src/com/android/car/messenger/MessengerDelegate.java b/src/com/android/car/messenger/MessengerDelegate.java index 6328905..28eeeee 100644 --- a/src/com/android/car/messenger/MessengerDelegate.java +++ b/src/com/android/car/messenger/MessengerDelegate.java @@ -7,6 +7,7 @@ import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothMapClient; +import android.bluetooth.BluetoothProfile; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; @@ -34,6 +35,7 @@ import com.android.car.apps.common.LetterTileDrawable; import com.android.car.messenger.bluetooth.BluetoothHelper; import com.android.car.messenger.bluetooth.BluetoothMonitor; import com.android.car.messenger.log.L; +import com.android.internal.annotations.GuardedBy; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; @@ -53,8 +55,10 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe private static final String TAG = "CM.MessengerDelegate"; // Static user name for building a MessagingStyle. private static final String STATIC_USER_NAME = "STATIC_USER_NAME"; + private static final Object mMapClientLock = new Object(); private final Context mContext; + @GuardedBy("mMapClientLock") private BluetoothMapClient mBluetoothMapClient; private NotificationManager mNotificationManager; private final SmsDatabaseHandler mSmsDatabaseHandler; @@ -112,12 +116,16 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe public void onDeviceConnected(BluetoothDevice device) { L.d(TAG, "Device connected: \t%s", device.getAddress()); mBTDeviceAddressToConnectionTimestamp.put(device.getAddress(), System.currentTimeMillis()); - if (mBluetoothMapClient != null && mShouldLoadExistingMessages) { - mBluetoothMapClient.getUnreadMessages(device); - } else { - // onDeviceConnected should be sent by BluetoothMapClient, so log if we run into this - // strange case. - L.e(TAG, "BluetoothMapClient is null after connecting to device."); + synchronized (mMapClientLock) { + if (mBluetoothMapClient != null) { + if (mShouldLoadExistingMessages) { + mBluetoothMapClient.getUnreadMessages(device); + } + } else { + // onDeviceConnected should be sent by BluetoothMapClient, so log if we run into + // this strange case. + L.e(TAG, "BluetoothMapClient is null after connecting to device."); + } } } @@ -131,24 +139,36 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe @Override public void onMapConnected(BluetoothMapClient client) { - if (mBluetoothMapClient == client) { - return; - } + List<BluetoothDevice> connectedDevices; + synchronized (mMapClientLock) { + if (mBluetoothMapClient == client) { + return; + } - if (mBluetoothMapClient != null) { - mBluetoothMapClient.close(); - } + if (mBluetoothMapClient != null) { + mBluetoothMapClient.close(); + } - mBluetoothMapClient = client; - for (BluetoothDevice device : client.getConnectedDevices()) { - onDeviceConnected(device); + mBluetoothMapClient = client; + connectedDevices = mBluetoothMapClient.getConnectedDevices(); + } + if (connectedDevices != null) { + for (BluetoothDevice device : connectedDevices) { + onDeviceConnected(device); + } } } @Override public void onMapDisconnected(int profile) { - mBluetoothMapClient = null; cleanupMessagesAndNotifications(key -> true); + synchronized (mMapClientLock) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null) { + adapter.closeProfileProxy(BluetoothProfile.MAP_CLIENT, mBluetoothMapClient); + } + mBluetoothMapClient = null; + } } @Override @@ -159,24 +179,27 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe protected void sendMessage(SenderKey senderKey, String messageText) { boolean success = false; // Even if the device is not connected, try anyway so that the reply in enqueued. - if (mBluetoothMapClient != null) { - NotificationInfo notificationInfo = mNotificationInfos.get(senderKey); - if (notificationInfo == null) { - L.w(TAG, "No notificationInfo found for senderKey: %s", senderKey); - } else if (notificationInfo.mSenderContactUri == null) { - L.w(TAG, "Do not have contact URI for sender!"); - } else { - Uri recipientUris[] = {Uri.parse(notificationInfo.mSenderContactUri)}; - - final int requestCode = senderKey.hashCode(); - - Intent intent = new Intent(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY); - PendingIntent sentIntent = PendingIntent.getBroadcast(mContext, requestCode, intent, - PendingIntent.FLAG_ONE_SHOT); - - success = BluetoothHelper.sendMessage(mBluetoothMapClient, - senderKey.getDeviceAddress(), recipientUris, messageText, - sentIntent, null); + synchronized (mMapClientLock) { + if (mBluetoothMapClient != null) { + NotificationInfo notificationInfo = mNotificationInfos.get(senderKey); + if (notificationInfo == null) { + L.w(TAG, "No notificationInfo found for senderKey: %s", senderKey); + } else if (notificationInfo.mSenderContactUri == null) { + L.w(TAG, "Do not have contact URI for sender!"); + } else { + Uri[] recipientUris = {Uri.parse(notificationInfo.mSenderContactUri)}; + + final int requestCode = senderKey.hashCode(); + + Intent intent = new Intent(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY); + PendingIntent sentIntent = PendingIntent.getBroadcast(mContext, requestCode, + intent, + PendingIntent.FLAG_ONE_SHOT); + + success = BluetoothHelper.sendMessage(mBluetoothMapClient, + senderKey.getDeviceAddress(), recipientUris, messageText, + sentIntent, null); + } } } @@ -196,7 +219,7 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe NotificationInfo info = mNotificationInfos.get(senderKey); for (MessageKey key : info.mMessageKeys) { MapMessage message = mMessages.get(key); - if (!message.isRead()) { + if (!message.isReadOnCar()) { message.markMessageAsRead(); mSmsDatabaseHandler.addOrUpdate(message); } @@ -299,8 +322,10 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe protected void cleanup() { cleanupMessagesAndNotifications(key -> true); - if (mBluetoothMapClient != null) { - mBluetoothMapClient.close(); + synchronized (mMapClientLock) { + if (mBluetoothMapClient != null) { + mBluetoothMapClient.close(); + } } } @@ -334,7 +359,7 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe .setUri(notificationInfo.mSenderContactUri) .build(); notificationInfo.mMessageKeys.stream().map(mMessages::get).forEachOrdered(message -> { - if (!message.isRead()) { + if (!message.isReadOnCar()) { messagingStyle.addMessage( message.getMessageText(), message.getReceiveTime(), @@ -426,7 +451,10 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe } BluetoothDevice device = adapter.getRemoteDevice(deviceAddress); - return mBluetoothMapClient.isUploadingSupported(device); + synchronized (mMapClientLock) { + return (mBluetoothMapClient != null) && mBluetoothMapClient.isUploadingSupported( + device); + } } /** diff --git a/src/com/android/car/messenger/SmsDatabaseHandler.java b/src/com/android/car/messenger/SmsDatabaseHandler.java index b672354..333d8d7 100644 --- a/src/com/android/car/messenger/SmsDatabaseHandler.java +++ b/src/com/android/car/messenger/SmsDatabaseHandler.java @@ -168,7 +168,7 @@ class SmsDatabaseHandler { newMessage.put(Telephony.Sms.PERSON, getContactId(mContentResolver, message.getSenderContactUri())); - newMessage.put(Telephony.Sms.READ, message.isRead()); + newMessage.put(Telephony.Sms.READ, (message.isReadOnPhone() || message.isReadOnCar())); return newMessage; } diff --git a/src/com/android/car/messenger/bluetooth/BluetoothMonitor.java b/src/com/android/car/messenger/bluetooth/BluetoothMonitor.java index 7640c1c..0015ebc 100644 --- a/src/com/android/car/messenger/bluetooth/BluetoothMonitor.java +++ b/src/com/android/car/messenger/bluetooth/BluetoothMonitor.java @@ -9,11 +9,13 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources.NotFoundException; import android.os.Parcelable; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import com.android.car.messenger.R; import com.android.car.messenger.log.L; import java.util.HashSet; @@ -153,6 +155,17 @@ public class BluetoothMonitor { private void onMapDisconnected(int profile) { mListeners.forEach(listener -> listener.onMapDisconnected(profile)); + boolean shouldReconnectToMap = false; + try { + shouldReconnectToMap = mContext.getResources().getBoolean( + R.bool.config_loadExistingMessages); + } catch (NotFoundException e) { + // Should only happen for robolectric unit tests + L.e(TAG, e, "Could not find loadExistingMessages config"); + } + if (shouldReconnectToMap) { + connectToMap(); + } } private void onSdpRecord(BluetoothDevice device, boolean supportsReply) { diff --git a/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java b/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java index 6e730f0..cf04da3 100644 --- a/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java +++ b/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java @@ -94,7 +94,8 @@ public class MessengerDelegateTest { long deviceConnectionTimestamp = mMessengerDelegate.mBTDeviceAddressToConnectionTimestamp.get(BLUETOOTH_ADDRESS_TWO); - assertThat(deviceConnectionTimestamp).isEqualTo(timestamp); + // Sometimes there is slight flakiness in the timestamps. + assertThat(deviceConnectionTimestamp-timestamp).isLessThan(5L); } @Test @@ -195,14 +196,30 @@ public class MessengerDelegateTest { MessengerDelegate.NotificationInfo info = mMessengerDelegate.mNotificationInfos.get( mSenderKey); MessengerDelegate.MessageKey key = info.mMessageKeys.get(0); - assertThat(mMessengerDelegate.mMessages.get(key).isRead()).isTrue(); + assertThat(mMessengerDelegate.mMessages.get(key).isReadOnCar()).isTrue(); + } + + @Test + public void testMessageReadOnPhone() { + Intent readMessageIntent = createMessageIntent(mMockBluetoothDeviceOne, "mockHandle", + "510-111-2222", "testSender", + "Hello", /* timestamp= */ System.currentTimeMillis() + 10000L, + /* isReadOnPhone */ true); + mMessengerDelegate.onMessageReceived(readMessageIntent); + + MessengerDelegate.NotificationInfo info = mMessengerDelegate.mNotificationInfos.get( + mSenderKey); + MessengerDelegate.MessageKey key = info.mMessageKeys.get(0); + assertThat(mMessengerDelegate.mMessages.get(key).isReadOnCar()).isFalse(); + assertThat(mMessengerDelegate.mMessages.get(key).isReadOnPhone()).isTrue(); } @Test public void testNotificationsNotShownForExistingMessages() { Intent existingMessageIntent = createMessageIntent(mMockBluetoothDeviceTwo, "mockHandle", "510-111-2222", "testSender", - "Hello", /* timestamp= */ System.currentTimeMillis() - 10000L); + "Hello", /* timestamp= */ System.currentTimeMillis() - 10000L, + /* isReadOnPhone */ false); mMessengerDelegate.onDeviceConnected(mMockBluetoothDeviceTwo); mMessengerDelegate.onMessageReceived(existingMessageIntent); @@ -212,13 +229,14 @@ public class MessengerDelegateTest { } private Intent createMessageIntent(BluetoothDevice device, String handle, String senderUri, - String senderName, String messageText, Long timestamp) { + String senderName, String messageText, Long timestamp, boolean isReadOnPhone) { Intent intent = new Intent(); intent.setAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE, handle); intent.putExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_URI, senderUri); intent.putExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_NAME, senderName); + intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_READ_STATUS, isReadOnPhone); intent.putExtra(android.content.Intent.EXTRA_TEXT, messageText); if (timestamp != null) { intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_TIMESTAMP, timestamp); @@ -240,7 +258,7 @@ public class MessengerDelegateTest { private void createMockMessages() { mMessageOneIntent= createMessageIntent(mMockBluetoothDeviceOne, "mockHandle", "510-111-2222", "testSender", - "Hello", /* timestamp= */ null); + "Hello", /* timestamp= */ null, /* isReadOnPhone */ false); mMessageOne = MapMessage.parseFrom(mMessageOneIntent); mMessageOneKey = new MessengerDelegate.MessageKey(mMessageOne); mSenderKey = new MessengerDelegate.SenderKey(mMessageOne); |