diff options
| author | 2018-11-09 12:19:16 +0000 | |
|---|---|---|
| committer | 2018-11-09 12:19:16 +0000 | |
| commit | 794bd34b7dfa12c4d1aba5134dadf585a72d912d (patch) | |
| tree | e9a7483b8c728e697062125a4be3d24e654c3868 | |
| parent | 0c9e5fe0048c5c4440c413d9df15a48a935c5d70 (diff) | |
| parent | d287485e1734a59a6492df349c7d6bc715035349 (diff) | |
Merge "Update ExtService to use suggestConversationActions API to generate replies"
| -rw-r--r-- | packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java | 19 | ||||
| -rw-r--r-- | packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java | 68 |
2 files changed, 69 insertions, 18 deletions
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java index 8fee822f11c0..6f437bd5d96f 100644 --- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java +++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java @@ -15,6 +15,7 @@ */ package android.ext.services.notification; +import static android.app.Notification.CATEGORY_MESSAGE; import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; @@ -148,6 +149,18 @@ public class NotificationEntry { return Objects.equals(getNotification().category, category); } + /** + * Similar to {@link #isCategory(String)}, but checking the public version of the notification, + * if available. + */ + public boolean isPublicVersionCategory(String category) { + Notification publicVersion = getNotification().publicVersion; + if (publicVersion == null) { + return false; + } + return Objects.equals(publicVersion.category, category); + } + public boolean isAudioAttributesUsage(int usage) { return mAttributes != null && mAttributes.getUsage() == usage; } @@ -175,9 +188,9 @@ public class NotificationEntry { } protected boolean isMessaging() { - return isCategory(Notification.CATEGORY_MESSAGE) - || hasStyle(Notification.MessagingStyle.class) - || hasInlineReply(); + return isCategory(CATEGORY_MESSAGE) + || isPublicVersionCategory(CATEGORY_MESSAGE) + || hasStyle(Notification.MessagingStyle.class); } public boolean hasInlineReply() { diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java index 37a98fd1dd6c..b2fc41783516 100644 --- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java +++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java @@ -19,23 +19,22 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.RemoteAction; -import android.app.RemoteInput; import android.content.Context; import android.os.Bundle; import android.os.Parcelable; import android.os.Process; -import android.os.SystemProperties; -import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.ArrayMap; +import android.view.textclassifier.ConversationActions; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; public class SmartActionsHelper { private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>(); @@ -50,12 +49,18 @@ public class SmartActionsHelper { private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400; private static final int MAX_ACTIONS_PER_LINK = 1; private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS; - // Allow us to test out smart reply with dumb suggestions, it is disabled by default. - // TODO: Removed this once we have the model. - private static final String SYS_PROP_SMART_REPLIES_EXPERIMENT = - "persist.sys.smart_replies_experiment"; + private static final int MAX_SUGGESTED_REPLIES = 3; - SmartActionsHelper() {} + private static final ConversationActions.TypeConfig TYPE_CONFIG = + new ConversationActions.TypeConfig.Builder().setIncludedTypes( + Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY)) + .includeTypesFromTextClassifier(false) + .build(); + private static final List<String> HINTS = + Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION); + + SmartActionsHelper() { + } /** * Adds action adjustments based on the notification contents. @@ -92,8 +97,31 @@ public class SmartActionsHelper { if (context == null) { return EMPTY_REPLY_LIST; } - // TODO: replaced this with our model when it is ready. - return new ArrayList<>(Arrays.asList("Yes, please", "No, thanks")); + TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class); + if (tcm == null) { + return EMPTY_REPLY_LIST; + } + CharSequence text = getMostSalientActionText(entry.getNotification()); + ConversationActions.Message message = + new ConversationActions.Message.Builder() + .setText(text) + .build(); + + ConversationActions.Request request = + new ConversationActions.Request.Builder(Collections.singletonList(message)) + .setMaxSuggestions(MAX_SUGGESTED_REPLIES) + .setHints(HINTS) + .setTypeConfig(TYPE_CONFIG) + .build(); + + TextClassifier textClassifier = tcm.getTextClassifier(); + List<ConversationActions.ConversationAction> conversationActions = + textClassifier.suggestConversationActions(request).getConversationActions(); + + return conversationActions.stream() + .map(conversationAction -> conversationAction.getTextReply()) + .filter(textReply -> !TextUtils.isEmpty(textReply)) + .collect(Collectors.toCollection(ArrayList::new)); } /** @@ -124,20 +152,30 @@ public class SmartActionsHelper { } private boolean isEligibleForReplyAdjustment(@NonNull NotificationEntry entry) { - if (!SystemProperties.getBoolean(SYS_PROP_SMART_REPLIES_EXPERIMENT, false)) { + if (!Process.myUserHandle().equals(entry.getSbn().getUser())) { return false; } - Notification notification = entry.getNotification(); - if (notification.actions == null) { + String pkg = entry.getSbn().getPackageName(); + if (TextUtils.isEmpty(pkg) || pkg.equals("android")) { + return false; + } + // For now, we are only interested in messages. + if (!entry.isMessaging()) { + return false; + } + // Does not make sense to provide suggested replies if it is not something that can be + // replied. + if (!entry.hasInlineReply()) { return false; } - return entry.hasInlineReply(); + return true; } /** Returns the text most salient for action extraction in a notification. */ @Nullable private CharSequence getMostSalientActionText(@NonNull Notification notification) { /* If it's messaging style, use the most recent message. */ + // TODO: Use the last few X messages instead and take the Person object into consideration. Parcelable[] messages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES); if (messages != null && messages.length != 0) { Bundle lastMessage = (Bundle) messages[messages.length - 1]; |