summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-08-15 04:38:47 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-08-15 04:38:47 +0000
commite0a300a31778bce16dba12aa1e7fa4ad9d0fa2bd (patch)
treee9632dee869aea8afb85a6ab456d570ad43b867b
parenta10890b1177b8472ab4c2ae84cb7dcfefbe16a37 (diff)
parent4a6a99f1710792ee2fb04884b0ba4f399789cec4 (diff)
downloadMessenger-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.xml3
-rw-r--r--src/com/android/car/messenger/MapMessage.java25
-rw-r--r--src/com/android/car/messenger/MessengerDelegate.java106
-rw-r--r--src/com/android/car/messenger/SmsDatabaseHandler.java2
-rw-r--r--src/com/android/car/messenger/bluetooth/BluetoothMonitor.java13
-rw-r--r--tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java28
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);