Add id to ConversationActions and conversationId to its Request

ID is used as session id when logging.
Conversation id is used for TextClassifier to keep track of ongoing
conversation.

BUG: 120803809
Test: atest TextClassifierTest.java
Test: atest ConversationActionsTest.java

Change-Id: Ifa2e25005efa9b16e480d9a06b376d726ea6d6d3
This commit is contained in:
Tony Mak
2018-12-11 19:38:53 +08:00
parent 343a957473
commit c4359bf17f
6 changed files with 125 additions and 21 deletions

View File

@@ -52593,9 +52593,10 @@ package android.view.inspector {
package android.view.textclassifier {
public final class ConversationActions implements android.os.Parcelable {
ctor public ConversationActions(java.util.List<android.view.textclassifier.ConversationActions.ConversationAction>);
ctor public ConversationActions(java.util.List<android.view.textclassifier.ConversationActions.ConversationAction>, java.lang.String);
method public int describeContents();
method public java.util.List<android.view.textclassifier.ConversationActions.ConversationAction> getConversationActions();
method public java.lang.String getId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions> CREATOR;
field public static final java.lang.String HINT_FOR_IN_APP = "in_app";
@@ -52656,6 +52657,7 @@ package android.view.textclassifier {
method public int describeContents();
method public java.lang.String getCallingPackageName();
method public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
method public java.lang.String getConversationId();
method public java.util.List<java.lang.String> getHints();
method public int getMaxSuggestions();
method public android.view.textclassifier.ConversationActions.TypeConfig getTypeConfig();
@@ -52666,6 +52668,7 @@ package android.view.textclassifier {
public static final class ConversationActions.Request.Builder {
ctor public ConversationActions.Request.Builder(java.util.List<android.view.textclassifier.ConversationActions.Message>);
method public android.view.textclassifier.ConversationActions.Request build();
method public android.view.textclassifier.ConversationActions.Request.Builder setConversationId(java.lang.String);
method public android.view.textclassifier.ConversationActions.Request.Builder setHints(java.util.List<java.lang.String>);
method public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(int);
method public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(android.view.textclassifier.ConversationActions.TypeConfig);

View File

@@ -139,17 +139,21 @@ public final class ConversationActions implements Parcelable {
*/
public static final String HINT_FOR_NOTIFICATION = "notification";
private List<ConversationAction> mConversationActions;
private final List<ConversationAction> mConversationActions;
private final String mId;
/** Constructs a {@link ConversationActions} object. */
public ConversationActions(@NonNull List<ConversationAction> conversationActions) {
public ConversationActions(
@NonNull List<ConversationAction> conversationActions, @Nullable String id) {
mConversationActions =
Collections.unmodifiableList(Preconditions.checkNotNull(conversationActions));
mId = id;
}
private ConversationActions(Parcel in) {
mConversationActions =
Collections.unmodifiableList(in.createTypedArrayList(ConversationAction.CREATOR));
mId = in.readString();
}
@Override
@@ -160,14 +164,26 @@ public final class ConversationActions implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedList(mConversationActions);
parcel.writeString(mId);
}
/** Returns an immutable list of {@link ConversationAction} objects. */
/**
* Returns an immutable list of {@link ConversationAction} objects, which are ordered from high
* confidence to low confidence.
*/
@NonNull
public List<ConversationAction> getConversationActions() {
return mConversationActions;
}
/**
* Returns the id, if one exists, for this object.
*/
@Nullable
public String getId() {
return mId;
}
/** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
public static final class ConversationAction implements Parcelable {
@@ -678,35 +694,37 @@ public final class ConversationActions implements Parcelable {
private final List<String> mHints;
@Nullable
private String mCallingPackageName;
@Nullable
private final String mConversationId;
private Request(
@NonNull List<Message> conversation,
@NonNull TypeConfig typeConfig,
int maxSuggestions,
String conversationId,
@Nullable @Hint List<String> hints) {
mConversation = Preconditions.checkNotNull(conversation);
mTypeConfig = Preconditions.checkNotNull(typeConfig);
mMaxSuggestions = maxSuggestions;
mConversationId = conversationId;
mHints = hints;
}
private static Request readFromParcel(Parcel in) {
List<Message> conversation = new ArrayList<>();
in.readParcelableList(conversation, null);
TypeConfig typeConfig = in.readParcelable(null);
int maxSuggestions = in.readInt();
String conversationId = in.readString();
List<String> hints = new ArrayList<>();
in.readStringList(hints);
String callingPackageName = in.readString();
Request request = new Request(
conversation,
typeConfig,
maxSuggestions,
conversationId,
hints);
request.setCallingPackageName(callingPackageName);
return request;
@@ -717,6 +735,7 @@ public final class ConversationActions implements Parcelable {
parcel.writeParcelableList(mConversation, flags);
parcel.writeParcelable(mTypeConfig, flags);
parcel.writeInt(mMaxSuggestions);
parcel.writeString(mConversationId);
parcel.writeStringList(mHints);
parcel.writeString(mCallingPackageName);
}
@@ -759,6 +778,16 @@ public final class ConversationActions implements Parcelable {
return mMaxSuggestions;
}
/**
* Return an unique identifier of the conversation that is generating actions for. This
* identifier is unique within the calling package only, so use it with
* {@link #getCallingPackageName()}.
*/
@Nullable
public String getConversationId() {
return mConversationId;
}
/** Returns an immutable list of hints */
@Nullable
@Hint
@@ -794,6 +823,8 @@ public final class ConversationActions implements Parcelable {
private TypeConfig mTypeConfig;
private int mMaxSuggestions;
@Nullable
private String mConversationId;
@Nullable
@Hint
private List<String> mHints;
@@ -823,7 +854,8 @@ public final class ConversationActions implements Parcelable {
return this;
}
/** Sets the maximum number of suggestions you want.
/**
* Sets the maximum number of suggestions you want.
* <p>
* Value 0 means no restriction.
*/
@@ -833,6 +865,15 @@ public final class ConversationActions implements Parcelable {
return this;
}
/**
* Sets an unique identifier of the conversation that is generating actions for.
*/
@NonNull
public Builder setConversationId(@Nullable String conversationId) {
mConversationId = conversationId;
return this;
}
/** Builds the {@link Request} object. */
@NonNull
public Request build() {
@@ -840,6 +881,7 @@ public final class ConversationActions implements Parcelable {
Collections.unmodifiableList(mConversation),
mTypeConfig == null ? new TypeConfig.Builder().build() : mTypeConfig,
mMaxSuggestions,
mConversationId,
mHints == null
? Collections.emptyList()
: Collections.unmodifiableList(mHints));

View File

@@ -349,7 +349,7 @@ public interface TextClassifier {
@NonNull ConversationActions.Request request) {
Preconditions.checkNotNull(request);
Utils.checkMainThread();
return new ConversationActions(Collections.emptyList());
return new ConversationActions(Collections.emptyList(), null);
}
/**

View File

@@ -387,7 +387,10 @@ public final class TextClassifierImpl implements TextClassifier {
Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
List<ConversationActions.ConversationAction> conversationActions = new ArrayList<>();
int maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length);
int maxSuggestions = nativeSuggestions.length;
if (request.getMaxSuggestions() > 0) {
maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length);
}
for (int i = 0; i < maxSuggestions; i++) {
ActionsSuggestionsModel.ActionSuggestion nativeSuggestion = nativeSuggestions[i];
String actionType = nativeSuggestion.getActionType();
@@ -400,7 +403,7 @@ public final class TextClassifierImpl implements TextClassifier {
.setConfidenceScore(nativeSuggestion.getScore())
.build());
}
return new ConversationActions(conversationActions);
return new ConversationActions(conversationActions, /*id*/ null);
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
Log.e(LOG_TAG, "Error suggesting conversation actions.", t);

View File

@@ -18,7 +18,6 @@ package android.view.textclassifier;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -375,7 +374,7 @@ public class TextClassifierTest {
ConversationActions.Message message =
new ConversationActions.Message.Builder(
ConversationActions.Message.PERSON_USER_REMOTE)
.setText("Hello")
.setText("Where are you?")
.build();
ConversationActions.TypeConfig typeConfig =
new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
@@ -384,19 +383,44 @@ public class TextClassifierTest {
.build();
ConversationActions.Request request =
new ConversationActions.Request.Builder(Collections.singletonList(message))
.setMaxSuggestions(3)
.setMaxSuggestions(1)
.setTypeConfig(typeConfig)
.build();
ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
assertTrue(conversationActions.getConversationActions().size() > 0);
assertTrue(conversationActions.getConversationActions().size() <= 3);
assertTrue(conversationActions.getConversationActions().size() == 1);
for (ConversationActions.ConversationAction conversationAction :
conversationActions.getConversationActions()) {
assertEquals(conversationAction.getType(), ConversationActions.TYPE_TEXT_REPLY);
assertNotNull(conversationAction.getTextReply());
assertTrue(conversationAction.getConfidenceScore() > 0);
assertTrue(conversationAction.getConfidenceScore() <= 1);
assertThat(conversationAction,
isConversationAction(ConversationActions.TYPE_TEXT_REPLY));
}
}
@Test
public void testSuggestConversationActions_textReplyOnly_noMax() {
if (isTextClassifierDisabled()) return;
ConversationActions.Message message =
new ConversationActions.Message.Builder(
ConversationActions.Message.PERSON_USER_REMOTE)
.setText("Where are you?")
.build();
ConversationActions.TypeConfig typeConfig =
new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
.setIncludedTypes(
Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
.build();
ConversationActions.Request request =
new ConversationActions.Request.Builder(Collections.singletonList(message))
.setTypeConfig(typeConfig)
.build();
ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
assertTrue(conversationActions.getConversationActions().size() > 1);
for (ConversationActions.ConversationAction conversationAction :
conversationActions.getConversationActions()) {
assertThat(conversationAction,
isConversationAction(ConversationActions.TYPE_TEXT_REPLY));
}
}
@@ -498,4 +522,36 @@ public class TextClassifierTest {
}
};
}
private static Matcher<ConversationActions.ConversationAction> isConversationAction(
String actionType) {
return new BaseMatcher<ConversationActions.ConversationAction>() {
@Override
public boolean matches(Object o) {
if (!(o instanceof ConversationActions.ConversationAction)) {
return false;
}
ConversationActions.ConversationAction conversationAction =
(ConversationActions.ConversationAction) o;
if (!actionType.equals(conversationAction.getType())) {
return false;
}
if (ConversationActions.TYPE_TEXT_REPLY.equals(actionType)) {
if (conversationAction.getTextReply() == null) {
return false;
}
}
if (conversationAction.getConfidenceScore() < 0
|| conversationAction.getConfidenceScore() > 1) {
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText("actionType=").appendValue(actionType);
}
};
}
}

View File

@@ -75,7 +75,7 @@ public class SmartActionHelperTest {
mContext.getSystemService(TextClassificationManager.class)
.setTextClassifier(mTextClassifier);
when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
.thenReturn(new ConversationActions(Collections.emptyList()));
.thenReturn(new ConversationActions(Collections.emptyList(), null));
when(mNotificationEntry.getSbn()).thenReturn(mStatusBarNotification);
// The notification is eligible to have smart suggestions.