diff options
author | SzuWei Lin <szuweilin@google.com> | 2020-09-01 18:23:29 +0800 |
---|---|---|
committer | SzuWei Lin <szuweilin@google.com> | 2020-09-01 18:23:29 +0800 |
commit | 35fbb2c617b1cc21bc0edab1eaffc508d197e1b9 (patch) | |
tree | 31d9f3769f860e6066f09379047675002e7162da | |
parent | a85736371a3ede01f837e8b597be69088765817c (diff) | |
parent | 416a62600d3ac3e1ae60fc64bfa06f9e2b5b782a (diff) | |
download | Messenger-android10-gsi.tar.gz |
Merge branch android10-qpr3-releaseandroid10-gsi
Change-Id: I784841e602189b2980db6e09f5ab87802b28619c
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | AndroidManifest.xml | 1 | ||||
-rw-r--r-- | src/com/android/car/messenger/MapMessage.java | 33 | ||||
-rw-r--r-- | src/com/android/car/messenger/MessengerDelegate.java | 43 | ||||
-rw-r--r-- | src/com/android/car/messenger/MessengerService.java | 13 | ||||
-rw-r--r-- | src/com/android/car/messenger/SmsDatabaseHandler.java | 3 | ||||
-rw-r--r-- | tests/robotests/src/com/android/car/messenger/MessengerDelegateTest.java | 6 |
7 files changed, 79 insertions, 23 deletions
@@ -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(); } |