summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzuWei Lin <szuweilin@google.com>2020-09-01 18:23:29 +0800
committerSzuWei Lin <szuweilin@google.com>2020-09-01 18:23:29 +0800
commit35fbb2c617b1cc21bc0edab1eaffc508d197e1b9 (patch)
tree31d9f3769f860e6066f09379047675002e7162da
parenta85736371a3ede01f837e8b597be69088765817c (diff)
parent416a62600d3ac3e1ae60fc64bfa06f9e2b5b782a (diff)
downloadMessenger-android10-gsi.tar.gz
Merge branch android10-qpr3-releaseandroid10-gsi
Change-Id: I784841e602189b2980db6e09f5ab87802b28619c
-rw-r--r--Android.mk3
-rw-r--r--AndroidManifest.xml1
-rw-r--r--src/com/android/car/messenger/MapMessage.java33
-rw-r--r--src/com/android/car/messenger/MessengerDelegate.java43
-rw-r--r--src/com/android/car/messenger/MessengerService.java13
-rw-r--r--src/com/android/car/messenger/SmsDatabaseHandler.java3
-rw-r--r--tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java6
7 files changed, 79 insertions, 23 deletions
diff --git a/Android.mk b/Android.mk
index 623b5ea..652d6e5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -38,8 +38,11 @@ LOCAL_PRIVILEGED_MODULE := true
LOCAL_USE_AAPT2 := true
+LOCAL_JAVA_LIBRARIES := android.car
+
LOCAL_STATIC_ANDROID_LIBRARIES += \
car-apps-common \
+ car-messenger-common \
car-telephony-common \
# Including the resources for the static android libraries allows to pick up their static overlays.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 75b7f8f..8d6754f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,6 +29,7 @@
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
+ <uses-permission android:name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"/>
<application android:label="@string/app_name">
<service android:name=".MessengerService"
diff --git a/src/com/android/car/messenger/MapMessage.java b/src/com/android/car/messenger/MapMessage.java
index b4b7aee..95c932d 100644
--- a/src/com/android/car/messenger/MapMessage.java
+++ b/src/com/android/car/messenger/MapMessage.java
@@ -19,6 +19,7 @@ package com.android.car.messenger;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothMapClient;
import android.content.Intent;
+import com.android.car.messenger.log.L;
import androidx.annotation.Nullable;
@@ -26,6 +27,7 @@ import androidx.annotation.Nullable;
* Represents a message obtained via MAP service from a connected Bluetooth device.
*/
class MapMessage {
+ private static final String TAG = "CM.MapMessage";
private String mDeviceAddress;
private String mHandle;
private String mSenderName;
@@ -34,18 +36,25 @@ class MapMessage {
private String mMessageText;
private long mReceiveTime;
private boolean mIsReadOnPhone;
- private boolean mIsReadOnCar;
+ private boolean mShouldInclude;
/**
* Constructs a {@link MapMessage} from {@code intent} that was received from MAP service via
* {@link BluetoothMapClient#ACTION_MESSAGE_RECEIVED} broadcast.
*
* @param intent intent received from MAP service
- * @return message constructed from extras in {@code intent}
+ * @return message constructed from extras in {@code intent}, or null if this is a group
+ * conversation.
* @throws NullPointerException if {@code intent} is missing the device extra
* @throws IllegalArgumentException if {@code intent} is missing any other required extras
*/
+ @Nullable
public static MapMessage parseFrom(Intent intent) {
+ if (intent.getStringArrayExtra(Intent.EXTRA_CC) != null
+ && intent.getStringArrayExtra(Intent.EXTRA_CC).length > 0) {
+ L.i(TAG, "Skipping group conversation message");
+ return null;
+ }
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String handle = intent.getStringExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE);
String senderUri = intent.getStringExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_URI);
@@ -101,6 +110,7 @@ class MapMessage {
mSenderName = senderName;
mReceiveTime = receiveTime;
mIsReadOnPhone = isRead;
+ mShouldInclude = true;
}
/**
@@ -151,8 +161,13 @@ class MapMessage {
return mMessageText;
}
- public void markMessageAsRead() {
- mIsReadOnCar = true;
+ /**
+ * Sets the message to be excluded from the notification. Messages that have been read aloud on
+ * the car, or that have been dismissed by the user should be excluded from the notification if/
+ * when the notification gets updated. Note: this state will not be propagated to the phone.
+ */
+ public void excludeFromNotification() {
+ mShouldInclude = false;
}
/**
@@ -163,10 +178,12 @@ class MapMessage {
}
/**
- * Returns {@code true} if message was read on the car.
+ * Returns {@code true} if message should be included in the notification. Messages that
+ * have been read aloud on the car, or that have been dismissed by the user should be excluded
+ * from the notification if/when the notification gets updated.
*/
- public boolean isReadOnCar() {
- return mIsReadOnCar;
+ public boolean shouldIncludeInNotification() {
+ return mShouldInclude;
}
@Override
@@ -179,7 +196,7 @@ class MapMessage {
", mSenderName='" + mSenderName + '\'' +
", mReceiveTime=" + mReceiveTime + '\'' +
", mIsReadOnPhone= " + mIsReadOnPhone + '\'' +
- ", mIsReadOnCar= " + mIsReadOnCar +
+ ", mShouldInclude= " + mShouldInclude +
"}";
}
}
diff --git a/src/com/android/car/messenger/MessengerDelegate.java b/src/com/android/car/messenger/MessengerDelegate.java
index 58193d4..7f864b6 100644
--- a/src/com/android/car/messenger/MessengerDelegate.java
+++ b/src/com/android/car/messenger/MessengerDelegate.java
@@ -14,7 +14,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -28,6 +27,7 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
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.common.ProjectionStateListener;
import com.android.car.messenger.log.L;
import com.android.car.telephony.common.TelecomUtils;
import com.android.internal.annotations.GuardedBy;
@@ -68,9 +68,15 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
final Map<String, Long> mBTDeviceAddressToConnectionTimestamp = new HashMap<>();
final Map<SenderKey, Bitmap> mSenderToLargeIconBitmap = new HashMap<>();
+ /** Tracks whether a projection application is active in the foreground. **/
+ private ProjectionStateListener mProjectionStateListener;
+
public MessengerDelegate(Context context) {
mContext = context;
+ mProjectionStateListener = new ProjectionStateListener(context);
+ mProjectionStateListener.start();
+
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mSmsDatabaseHandler = new SmsDatabaseHandler(mContext);
@@ -94,6 +100,7 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
public void onMessageReceived(Intent intent) {
try {
MapMessage message = MapMessage.parseFrom(intent);
+ if (message == null) return;
L.d(TAG, "Received message from " + message.getDeviceAddress());
MessageKey messageKey = new MessageKey(message);
@@ -210,12 +217,17 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
}
}
- protected void markAsRead(SenderKey senderKey) {
+
+ /**
+ * Excludes messages from a notification so that the messages are not shown to the user once
+ * the notification gets updated with newer messages.
+ */
+ protected void excludeFromNotification(SenderKey senderKey) {
NotificationInfo info = mNotificationInfos.get(senderKey);
for (MessageKey key : info.mMessageKeys) {
MapMessage message = mMessages.get(key);
- if (!message.isReadOnCar()) {
- message.markMessageAsRead();
+ if (message.shouldIncludeInNotification()) {
+ message.excludeFromNotification();
mSmsDatabaseHandler.addOrUpdate(message);
}
}
@@ -227,6 +239,7 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
if (mPhoneNumberInfoFuture != null) {
mPhoneNumberInfoFuture.cancel(true);
}
+ mProjectionStateListener.stop();
}
/**
@@ -239,6 +252,7 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
if (predicate.test(senderKey)) {
mNotificationManager.cancel(notificationInfo.mNotificationId);
}
+ excludeFromNotification(senderKey);
});
}
@@ -249,11 +263,11 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
mSmsDatabaseHandler.removeMessagesForDevice(key.getDeviceAddress());
}
}
- mMessages.entrySet().removeIf(
- messageKeyMapMessageEntry -> predicate.test(messageKeyMapMessageEntry.getKey()));
clearNotifications(predicate);
mNotificationInfos.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
mSenderToLargeIconBitmap.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
+ mMessages.entrySet().removeIf(
+ messageKeyMapMessageEntry -> predicate.test(messageKeyMapMessageEntry.getKey()));
}
private void updateNotification(MessageKey messageKey, MapMessage mapMessage) {
@@ -361,17 +375,26 @@ public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListe
.setUri(notificationInfo.mSenderContactUri)
.build();
notificationInfo.mMessageKeys.stream().map(mMessages::get).forEachOrdered(message -> {
- if (!message.isReadOnCar()) {
+ if (message.shouldIncludeInNotification()) {
messagingStyle.addMessage(
message.getMessageText(),
message.getReceiveTime(),
sender);
+ } else {
+ L.d(TAG, "excluding message received at: " + message.getReceiveTime()
+ + " from notification.");
}
});
- NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext,
- MessengerService.SMS_CHANNEL_ID)
- .setContentTitle(senderName)
+ NotificationCompat.Builder builder;
+ if (mProjectionStateListener.isProjectionInActiveForeground(senderKey.getDeviceAddress())) {
+ builder = new NotificationCompat.Builder(mContext,
+ MessengerService.SILENT_SMS_CHANNEL_ID);
+ } else {
+ builder = new NotificationCompat.Builder(mContext, MessengerService.SMS_CHANNEL_ID);
+ }
+
+ builder.setContentTitle(senderName)
.setContentText(contentText)
.setStyle(messagingStyle)
.setCategory(Notification.CATEGORY_MESSAGE)
diff --git a/src/com/android/car/messenger/MessengerService.java b/src/com/android/car/messenger/MessengerService.java
index 0b0e4e4..2f71de5 100644
--- a/src/com/android/car/messenger/MessengerService.java
+++ b/src/com/android/car/messenger/MessengerService.java
@@ -59,6 +59,7 @@ public class MessengerService extends Service {
/* NOTIFICATIONS */
static final String SMS_CHANNEL_ID = "SMS_CHANNEL_ID";
+ static final String SILENT_SMS_CHANNEL_ID = "SILENT_SMS_CHANNEL_ID";
private static final String APP_RUNNING_CHANNEL_ID = "APP_RUNNING_CHANNEL_ID";
private static final int SERVICE_STARTED_NOTIFICATION_ID = Integer.MAX_VALUE;
@@ -111,6 +112,16 @@ public class MessengerService extends Service {
notificationManager.createNotificationChannel(appRunningNotificationChannel);
}
+ // Create notification channel for notifications that should be posted silently in the
+ // notification center, without a heads up notification.
+ {
+ NotificationChannel silentNotificationChannel =
+ new NotificationChannel(SILENT_SMS_CHANNEL_ID,
+ getString(R.string.sms_channel_description),
+ NotificationManager.IMPORTANCE_LOW);
+ notificationManager.createNotificationChannel(silentNotificationChannel);
+ }
+
{
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
@@ -243,7 +254,7 @@ public class MessengerService extends Service {
public void markAsRead(Intent intent) {
final SenderKey senderKey = intent.getParcelableExtra(EXTRA_SENDER_KEY);
L.d(TAG, "markAsRead");
- mMessengerDelegate.markAsRead(senderKey);
+ mMessengerDelegate.excludeFromNotification(senderKey);
}
/**
diff --git a/src/com/android/car/messenger/SmsDatabaseHandler.java b/src/com/android/car/messenger/SmsDatabaseHandler.java
index 77d8e29..a8fd107 100644
--- a/src/com/android/car/messenger/SmsDatabaseHandler.java
+++ b/src/com/android/car/messenger/SmsDatabaseHandler.java
@@ -168,7 +168,8 @@ class SmsDatabaseHandler {
newMessage.put(Telephony.Sms.PERSON,
getContactId(mContentResolver,
message.getSenderContactUri()));
- newMessage.put(Telephony.Sms.READ, (message.isReadOnPhone() || message.isReadOnCar()));
+ newMessage.put(Telephony.Sms.READ, (message.isReadOnPhone()
+ || !message.shouldIncludeInNotification()));
return newMessage;
}
diff --git a/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java b/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java
index b160736..5720497 100644
--- a/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java
+++ b/tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java
@@ -191,12 +191,12 @@ public class MessengerDelegateTest {
public void testHandleMarkAsRead() {
mMessengerDelegate.onMessageReceived(mMessageOneIntent);
- mMessengerDelegate.markAsRead(mSenderKey);
+ mMessengerDelegate.excludeFromNotification(mSenderKey);
MessengerDelegate.NotificationInfo info = mMessengerDelegate.mNotificationInfos.get(
mSenderKey);
MessengerDelegate.MessageKey key = info.mMessageKeys.get(0);
- assertThat(mMessengerDelegate.mMessages.get(key).isReadOnCar()).isTrue();
+ assertThat(mMessengerDelegate.mMessages.get(key).shouldIncludeInNotification()).isFalse();
}
@Test
@@ -210,7 +210,7 @@ public class MessengerDelegateTest {
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).shouldIncludeInNotification()).isTrue();
assertThat(mMessengerDelegate.mMessages.get(key).isReadOnPhone()).isTrue();
}