Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18ff8961 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Introduce Message.USER_LOCAL and added logic to map person to user id"

parents 88dbb1b2 f99ee17f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+2 −2
Original line number Diff line number Diff line
@@ -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
+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;
        }
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -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
@@ -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;
+11 −19
Original line number Diff line number Diff line
@@ -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;
@@ -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