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

Commit ae33c3bd authored by Tony Mak's avatar Tony Mak
Browse files

Support intent configuration for actions

1. Pull out the common intent genereation logic to TemplateIntentFactory,
so that it could be used by actions.

2. Fix a bug that we are freeing the annotator immediately when
   we are switching annotator model file. It is incorrect as
   it could be used by another thread / model.

Test: atest frameworks/base/core/tests/coretests/src/android/view/textclassifier/

BUG: 123745079

Change-Id: I6c5364595470b900be2dd976dda6e9fc90464de9
parent 80ced71a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -53563,7 +53563,7 @@ package android.view.textclassifier {
    method @NonNull public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
    method @Nullable public String getConversationId();
    method @Nullable public java.util.List<java.lang.String> getHints();
    method @IntRange(from=0) public int getMaxSuggestions();
    method @IntRange(from=0xffffffff) public int getMaxSuggestions();
    method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Request> CREATOR;
@@ -53576,7 +53576,7 @@ package android.view.textclassifier {
    method @NonNull public android.view.textclassifier.ConversationActions.Request build();
    method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setConversationId(@Nullable String);
    method public android.view.textclassifier.ConversationActions.Request.Builder setHints(@Nullable java.util.List<java.lang.String>);
    method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0) int);
    method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0xffffffff) int);
    method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
  }
+7 −7
Original line number Diff line number Diff line
@@ -393,9 +393,10 @@ public final class ConversationActions implements Parcelable {
        }

        /**
         * Return the maximal number of suggestions the caller wants, value 0 means no restriction.
         * Return the maximal number of suggestions the caller wants, value -1 means no restriction
         * and this is the default.
         */
        @IntRange(from = 0)
        @IntRange(from = -1)
        public int getMaxSuggestions() {
            return mMaxSuggestions;
        }
@@ -443,7 +444,7 @@ public final class ConversationActions implements Parcelable {
            private List<Message> mConversation;
            @Nullable
            private TextClassifier.EntityConfig mTypeConfig;
            private int mMaxSuggestions;
            private int mMaxSuggestions = -1;
            @Nullable
            private String mConversationId;
            @Nullable
@@ -477,12 +478,11 @@ public final class ConversationActions implements Parcelable {
            }

            /**
             * Sets the maximum number of suggestions you want.
             * <p>
             * Value 0 means no restriction.
             * Sets the maximum number of suggestions you want. Value -1 means no restriction and
             * this is the default.
             */
            @NonNull
            public Builder setMaxSuggestions(@IntRange(from = 0) int maxSuggestions) {
            public Builder setMaxSuggestions(@IntRange(from = -1) int maxSuggestions) {
                mMaxSuggestions = Preconditions.checkArgumentNonnegative(maxSuggestions);
                return this;
            }
+2 −1
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ public interface IntentFactory {
                new Intent(Intent.ACTION_TRANSLATE)
                        // TODO: Probably better to introduce a "translate" scheme instead of
                        // using EXTRA_TEXT.
                        .putExtra(Intent.EXTRA_TEXT, text),
                        .putExtra(Intent.EXTRA_TEXT, text)
                        .putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true),
                text.hashCode()));
    }
}
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.annotation.Nullable;
import android.content.Context;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;

import com.google.android.textclassifier.AnnotatorModel;
import com.google.android.textclassifier.RemoteActionTemplate;

import java.time.Instant;
import java.util.Collections;
import java.util.List;

/**
 * Creates intents based on {@link RemoteActionTemplate} objects for a ClassificationResult.
 *
 * @hide
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class TemplateClassificationIntentFactory implements IntentFactory {
    private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
    private final TemplateIntentFactory mTemplateIntentFactory;
    private final IntentFactory mFallback;

    public TemplateClassificationIntentFactory(TemplateIntentFactory templateIntentFactory,
            IntentFactory fallback) {
        mTemplateIntentFactory = Preconditions.checkNotNull(templateIntentFactory);
        mFallback = Preconditions.checkNotNull(fallback);
    }

    /**
     * Returns a list of {@link android.view.textclassifier.TextClassifierImpl.LabeledIntent}
     * that are constructed from the classification result.
     */
    @NonNull
    @Override
    public List<TextClassifierImpl.LabeledIntent> create(
            Context context,
            String text,
            boolean foreignText,
            @Nullable Instant referenceTime,
            @Nullable AnnotatorModel.ClassificationResult classification) {
        if (classification == null) {
            return Collections.emptyList();
        }
        RemoteActionTemplate[] remoteActionTemplates = classification.getRemoteActionTemplates();
        if (ArrayUtils.isEmpty(remoteActionTemplates)) {
            // RemoteActionTemplate is missing, fallback.
            Log.w(TAG, "RemoteActionTemplate is missing, fallback to LegacyIntentFactory.");
            return mFallback.create(context, text, foreignText, referenceTime, classification);
        }
        final List<TextClassifierImpl.LabeledIntent> labeledIntents =
                mTemplateIntentFactory.create(remoteActionTemplates);
        if (foreignText) {
            IntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
        }
        return labeledIntents;
    }
}
+7 −40
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package android.view.textclassifier;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -25,64 +24,29 @@ import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;

import com.google.android.textclassifier.AnnotatorModel;
import com.google.android.textclassifier.NamedVariant;
import com.google.android.textclassifier.RemoteActionTemplate;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Creates intents based on {@link RemoteActionTemplate} objects.
 *
 * @hide
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class TemplateIntentFactory implements IntentFactory {
public final class TemplateIntentFactory {
    private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
    private final IntentFactory mFallback;

    public TemplateIntentFactory(IntentFactory fallback) {
        mFallback = Preconditions.checkNotNull(fallback);
    }

    /**
     * Returns a list of {@link android.view.textclassifier.TextClassifierImpl.LabeledIntent}
     * that are constructed from the classification result.
     */
    @NonNull
    @Override
    public List<TextClassifierImpl.LabeledIntent> create(
            Context context,
            String text,
            boolean foreignText,
            @Nullable Instant referenceTime,
            @Nullable AnnotatorModel.ClassificationResult classification) {
        if (classification == null) {
            return Collections.emptyList();
        }
        RemoteActionTemplate[] remoteActionTemplates = classification.getRemoteActionTemplates();
            @Nullable RemoteActionTemplate[] remoteActionTemplates) {
        if (ArrayUtils.isEmpty(remoteActionTemplates)) {
            // RemoteActionTemplate is missing, fallback.
            Log.w(TAG, "RemoteActionTemplate is missing, fallback to LegacyIntentFactory.");
            return mFallback.create(context, text, foreignText, referenceTime, classification);
        }
        final List<TextClassifierImpl.LabeledIntent> labeledIntents =
                new ArrayList<>(createFromRemoteActionTemplates(remoteActionTemplates));
        if (foreignText) {
            IntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
        }
        labeledIntents.forEach(
                action -> action.getIntent()
                        .putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true));
        return labeledIntents;
            return Collections.emptyList();
        }

    private static List<TextClassifierImpl.LabeledIntent> createFromRemoteActionTemplates(
            RemoteActionTemplate[] remoteActionTemplates) {
        final List<TextClassifierImpl.LabeledIntent> labeledIntents = new ArrayList<>();
        for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
            Intent intent = createIntent(remoteActionTemplate);
@@ -100,6 +64,9 @@ public final class TemplateIntentFactory implements IntentFactory {
            );
            labeledIntents.add(labeledIntent);
        }
        labeledIntents.forEach(
                action -> action.getIntent()
                        .putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true));
        return labeledIntents;
    }

Loading