Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -51922,6 +51922,7 @@ package android.view.textclassifier { method public java.time.ZonedDateTime getTime(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Message> CREATOR; field public static final android.app.Person PERSON_USER_LOCAL; } public static final class ConversationActions.Message.Builder { core/java/android/app/Person.java +2 −2 Original line number Diff line number Diff line Loading @@ -127,8 +127,8 @@ public final class Person implements Parcelable { if (obj instanceof Person) { final Person other = (Person) obj; return Objects.equals(mName, other.mName) && mIcon == null ? other.mIcon == null : (other.mIcon != null && mIcon.sameAs(other.mIcon)) && (mIcon == null ? other.mIcon == null : (other.mIcon != null && mIcon.sameAs(other.mIcon))) && Objects.equals(mUri, other.mUri) && Objects.equals(mKey, other.mKey) && mIsBot == other.mIsBot Loading core/java/android/view/textclassifier/ActionsSuggestionsHelper.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.textclassifier; import android.annotation.NonNull; import android.app.Person; import android.text.TextUtils; import android.util.ArrayMap; import com.android.internal.annotations.VisibleForTesting; import com.google.android.textclassifier.ActionsSuggestionsModel; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * Helper class for action suggestions. * * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class ActionsSuggestionsHelper { private static final int USER_LOCAL = 0; private static final int FIRST_NON_LOCAL_USER = 1; private ActionsSuggestionsHelper() {} /** * Converts the messages to a list of native messages object that the model can understand. * <p> * User id encoding - local user is represented as 0, Other users are numbered according to * how far before they spoke last time in the conversation. For example, considering this * conversation: * <ul> * <li> User A: xxx * <li> Local user: yyy * <li> User B: zzz * </ul> * User A will be encoded as 2, user B will be encoded as 1 and local user will be encoded as 0. */ @NonNull public static ActionsSuggestionsModel.ConversationMessage[] toNativeMessages( @NonNull List<ConversationActions.Message> messages) { List<ConversationActions.Message> messagesWithText = messages.stream() .filter(message -> !TextUtils.isEmpty(message.getText())) .collect(Collectors.toCollection(ArrayList::new)); if (messagesWithText.isEmpty()) { return new ActionsSuggestionsModel.ConversationMessage[0]; } int size = messagesWithText.size(); // If the last message (the most important one) does not have the Person object, we will // just use the last message and consider this message is sent from a remote user. ConversationActions.Message lastMessage = messages.get(size - 1); boolean useLastMessageOnly = lastMessage.getAuthor() == null; if (useLastMessageOnly) { return new ActionsSuggestionsModel.ConversationMessage[]{ new ActionsSuggestionsModel.ConversationMessage( FIRST_NON_LOCAL_USER, lastMessage.getText().toString())}; } // Encode the messages in the reverse order, stop whenever the Person object is missing. Deque<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayDeque<>(); PersonEncoder personEncoder = new PersonEncoder(); for (int i = size - 1; i >= 0; i--) { ConversationActions.Message message = messagesWithText.get(i); if (message.getAuthor() == null) { break; } nativeMessages.push(new ActionsSuggestionsModel.ConversationMessage( personEncoder.encode(message.getAuthor()), message.getText().toString())); } return nativeMessages.toArray( new ActionsSuggestionsModel.ConversationMessage[nativeMessages.size()]); } private static final class PersonEncoder { private final Map<Person, Integer> mMapping = new ArrayMap<>(); private int mNextUserId = FIRST_NON_LOCAL_USER; private int encode(Person person) { if (ConversationActions.Message.PERSON_USER_LOCAL.equals(person)) { return USER_LOCAL; } Integer result = mMapping.get(person); if (result == null) { mMapping.put(person, mNextUserId); result = mNextUserId; mNextUserId++; } return result; } } } core/java/android/view/textclassifier/ConversationActions.java +15 −1 Original line number Diff line number Diff line Loading @@ -345,6 +345,16 @@ public final class ConversationActions implements Parcelable { /** Represents a message in the conversation. */ public static final class Message implements Parcelable { /** * Represents the local user. * * @see Builder#setAuthor(Person) */ public static final Person PERSON_USER_LOCAL = new Person.Builder() .setKey("text-classifier-conversation-actions-local-user") .build(); @Nullable private final Person mAuthor; @Nullable Loading Loading @@ -446,7 +456,11 @@ public final class ConversationActions implements Parcelable { @Nullable private Bundle mExtras; /** Sets the person who composed this message. */ /** * Sets the person who composed this message. * <p> * Use {@link #PERSON_USER_LOCAL} to represent the local user. */ @NonNull public Builder setAuthor(@Nullable Person author) { mAuthor = author; Loading core/java/android/view/textclassifier/TextClassifierImpl.java +11 −19 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ import android.os.UserManager; import android.provider.Browser; import android.provider.CalendarContract; import android.provider.ContactsContract; import android.text.TextUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; Loading Loading @@ -372,20 +371,13 @@ public final class TextClassifierImpl implements TextClassifier { // Actions model is optional, fallback if it is not available. return mFallback.suggestConversationActions(request); } List<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayList<>(); for (ConversationActions.Message message : request.getConversation()) { if (TextUtils.isEmpty(message.getText())) { continue; } // TODO: We need to map the Person object to user id. int userId = 1; nativeMessages.add( new ActionsSuggestionsModel.ConversationMessage( userId, message.getText().toString())); ActionsSuggestionsModel.ConversationMessage[] nativeMessages = ActionsSuggestionsHelper.toNativeMessages(request.getConversation()); if (nativeMessages.length == 0) { return mFallback.suggestConversationActions(request); } ActionsSuggestionsModel.Conversation nativeConversation = new ActionsSuggestionsModel.Conversation(nativeMessages.toArray( new ActionsSuggestionsModel.ConversationMessage[0])); new ActionsSuggestionsModel.Conversation(nativeMessages); ActionsSuggestionsModel.ActionSuggestion[] nativeSuggestions = actionsImpl.suggestActions(nativeConversation, null); Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -51922,6 +51922,7 @@ package android.view.textclassifier { method public java.time.ZonedDateTime getTime(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Message> CREATOR; field public static final android.app.Person PERSON_USER_LOCAL; } public static final class ConversationActions.Message.Builder {
core/java/android/app/Person.java +2 −2 Original line number Diff line number Diff line Loading @@ -127,8 +127,8 @@ public final class Person implements Parcelable { if (obj instanceof Person) { final Person other = (Person) obj; return Objects.equals(mName, other.mName) && mIcon == null ? other.mIcon == null : (other.mIcon != null && mIcon.sameAs(other.mIcon)) && (mIcon == null ? other.mIcon == null : (other.mIcon != null && mIcon.sameAs(other.mIcon))) && Objects.equals(mUri, other.mUri) && Objects.equals(mKey, other.mKey) && mIsBot == other.mIsBot Loading
core/java/android/view/textclassifier/ActionsSuggestionsHelper.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.textclassifier; import android.annotation.NonNull; import android.app.Person; import android.text.TextUtils; import android.util.ArrayMap; import com.android.internal.annotations.VisibleForTesting; import com.google.android.textclassifier.ActionsSuggestionsModel; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * Helper class for action suggestions. * * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class ActionsSuggestionsHelper { private static final int USER_LOCAL = 0; private static final int FIRST_NON_LOCAL_USER = 1; private ActionsSuggestionsHelper() {} /** * Converts the messages to a list of native messages object that the model can understand. * <p> * User id encoding - local user is represented as 0, Other users are numbered according to * how far before they spoke last time in the conversation. For example, considering this * conversation: * <ul> * <li> User A: xxx * <li> Local user: yyy * <li> User B: zzz * </ul> * User A will be encoded as 2, user B will be encoded as 1 and local user will be encoded as 0. */ @NonNull public static ActionsSuggestionsModel.ConversationMessage[] toNativeMessages( @NonNull List<ConversationActions.Message> messages) { List<ConversationActions.Message> messagesWithText = messages.stream() .filter(message -> !TextUtils.isEmpty(message.getText())) .collect(Collectors.toCollection(ArrayList::new)); if (messagesWithText.isEmpty()) { return new ActionsSuggestionsModel.ConversationMessage[0]; } int size = messagesWithText.size(); // If the last message (the most important one) does not have the Person object, we will // just use the last message and consider this message is sent from a remote user. ConversationActions.Message lastMessage = messages.get(size - 1); boolean useLastMessageOnly = lastMessage.getAuthor() == null; if (useLastMessageOnly) { return new ActionsSuggestionsModel.ConversationMessage[]{ new ActionsSuggestionsModel.ConversationMessage( FIRST_NON_LOCAL_USER, lastMessage.getText().toString())}; } // Encode the messages in the reverse order, stop whenever the Person object is missing. Deque<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayDeque<>(); PersonEncoder personEncoder = new PersonEncoder(); for (int i = size - 1; i >= 0; i--) { ConversationActions.Message message = messagesWithText.get(i); if (message.getAuthor() == null) { break; } nativeMessages.push(new ActionsSuggestionsModel.ConversationMessage( personEncoder.encode(message.getAuthor()), message.getText().toString())); } return nativeMessages.toArray( new ActionsSuggestionsModel.ConversationMessage[nativeMessages.size()]); } private static final class PersonEncoder { private final Map<Person, Integer> mMapping = new ArrayMap<>(); private int mNextUserId = FIRST_NON_LOCAL_USER; private int encode(Person person) { if (ConversationActions.Message.PERSON_USER_LOCAL.equals(person)) { return USER_LOCAL; } Integer result = mMapping.get(person); if (result == null) { mMapping.put(person, mNextUserId); result = mNextUserId; mNextUserId++; } return result; } } }
core/java/android/view/textclassifier/ConversationActions.java +15 −1 Original line number Diff line number Diff line Loading @@ -345,6 +345,16 @@ public final class ConversationActions implements Parcelable { /** Represents a message in the conversation. */ public static final class Message implements Parcelable { /** * Represents the local user. * * @see Builder#setAuthor(Person) */ public static final Person PERSON_USER_LOCAL = new Person.Builder() .setKey("text-classifier-conversation-actions-local-user") .build(); @Nullable private final Person mAuthor; @Nullable Loading Loading @@ -446,7 +456,11 @@ public final class ConversationActions implements Parcelable { @Nullable private Bundle mExtras; /** Sets the person who composed this message. */ /** * Sets the person who composed this message. * <p> * Use {@link #PERSON_USER_LOCAL} to represent the local user. */ @NonNull public Builder setAuthor(@Nullable Person author) { mAuthor = author; Loading
core/java/android/view/textclassifier/TextClassifierImpl.java +11 −19 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ import android.os.UserManager; import android.provider.Browser; import android.provider.CalendarContract; import android.provider.ContactsContract; import android.text.TextUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; Loading Loading @@ -372,20 +371,13 @@ public final class TextClassifierImpl implements TextClassifier { // Actions model is optional, fallback if it is not available. return mFallback.suggestConversationActions(request); } List<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayList<>(); for (ConversationActions.Message message : request.getConversation()) { if (TextUtils.isEmpty(message.getText())) { continue; } // TODO: We need to map the Person object to user id. int userId = 1; nativeMessages.add( new ActionsSuggestionsModel.ConversationMessage( userId, message.getText().toString())); ActionsSuggestionsModel.ConversationMessage[] nativeMessages = ActionsSuggestionsHelper.toNativeMessages(request.getConversation()); if (nativeMessages.length == 0) { return mFallback.suggestConversationActions(request); } ActionsSuggestionsModel.Conversation nativeConversation = new ActionsSuggestionsModel.Conversation(nativeMessages.toArray( new ActionsSuggestionsModel.ConversationMessage[0])); new ActionsSuggestionsModel.Conversation(nativeMessages); ActionsSuggestionsModel.ActionSuggestion[] nativeSuggestions = actionsImpl.suggestActions(nativeConversation, null); Loading