Fallback to legacy intent factory when the template is null
When RemoteActionTemplate[] is null, it means the intent generator
is not working, we then fallback to legacy intent factory
If RemoteActionTemplate[] is an empty array, it means the intent
generator is run, but no intent is generated.
Also, moved all intent related class to intent/ folder
Test: atest frameworks/base/core/tests/coretests/src/android/view/textclassifier/
Change-Id: I7e4c49dc3ebed4d498ac26f0894d7af85419419e
diff --git a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
index 17edf5c..e7ae7a0 100644
--- a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
+++ b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
@@ -23,10 +23,13 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Pair;
+import android.view.textclassifier.intent.LabeledIntent;
+import android.view.textclassifier.intent.TemplateIntentFactory;
import com.android.internal.annotations.VisibleForTesting;
import com.google.android.textclassifier.ActionsSuggestionsModel;
+import com.google.android.textclassifier.RemoteActionTemplate;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -46,6 +49,7 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class ActionsSuggestionsHelper {
+ private static final String TAG = "ActionsSuggestions";
private static final int USER_LOCAL = 0;
private static final int FIRST_NON_LOCAL_USER = 1;
@@ -117,8 +121,33 @@
}
/**
- * Returns a {@link android.view.textclassifier.LabeledIntent.TitleChooser} for
- * conversation actions use case.
+ * Generated labeled intent from an action suggestion and return the resolved result.
+ */
+ @Nullable
+ public static LabeledIntent.Result createLabeledIntentResult(
+ Context context,
+ TemplateIntentFactory templateIntentFactory,
+ ActionsSuggestionsModel.ActionSuggestion nativeSuggestion) {
+ RemoteActionTemplate[] remoteActionTemplates =
+ nativeSuggestion.getRemoteActionTemplates();
+ if (remoteActionTemplates == null) {
+ Log.w(TAG, "createRemoteAction: Missing template for type "
+ + nativeSuggestion.getActionType());
+ return null;
+ }
+ List<LabeledIntent> labeledIntents = templateIntentFactory.create(remoteActionTemplates);
+ if (labeledIntents.isEmpty()) {
+ return null;
+ }
+ // Given that we only support implicit intent here, we should expect there is just one
+ // intent for each action type.
+ LabeledIntent.TitleChooser titleChooser =
+ ActionsSuggestionsHelper.createTitleChooser(nativeSuggestion.getActionType());
+ return labeledIntents.get(0).resolve(context, titleChooser);
+ }
+
+ /**
+ * Returns a {@link LabeledIntent.TitleChooser} for conversation actions use case.
*/
@Nullable
public static LabeledIntent.TitleChooser createTitleChooser(String actionType) {
diff --git a/core/java/android/view/textclassifier/Log.java b/core/java/android/view/textclassifier/Log.java
index 5c60c09..03ed496 100644
--- a/core/java/android/view/textclassifier/Log.java
+++ b/core/java/android/view/textclassifier/Log.java
@@ -22,8 +22,10 @@
* To enable full log:
* 1. adb shell setprop log.tag.androidtc VERBOSE
* 2. adb shell stop && adb shell start
+ *
+ * @hide
*/
-final class Log {
+public final class Log {
/**
* true: Enables full logging.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 0f3a8cf..8b9f189 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -25,6 +25,11 @@
import android.os.Bundle;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
+import android.view.textclassifier.intent.ClassificationIntentFactory;
+import android.view.textclassifier.intent.LabeledIntent;
+import android.view.textclassifier.intent.LegacyClassificationIntentFactory;
+import android.view.textclassifier.intent.TemplateClassificationIntentFactory;
+import android.view.textclassifier.intent.TemplateIntentFactory;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
@@ -110,7 +115,7 @@
private final ModelFileManager mLangIdModelFileManager;
private final ModelFileManager mActionsModelFileManager;
- private final IntentFactory mIntentFactory;
+ private final ClassificationIntentFactory mClassificationIntentFactory;
private final TemplateIntentFactory mTemplateIntentFactory;
public TextClassifierImpl(
@@ -142,10 +147,10 @@
ActionsSuggestionsModel::getLocales));
mTemplateIntentFactory = new TemplateIntentFactory();
- mIntentFactory = mSettings.isTemplateIntentFactoryEnabled()
+ mClassificationIntentFactory = mSettings.isTemplateIntentFactoryEnabled()
? new TemplateClassificationIntentFactory(
- mTemplateIntentFactory, new LegacyIntentFactory())
- : new LegacyIntentFactory();
+ mTemplateIntentFactory, new LegacyClassificationIntentFactory())
+ : new LegacyClassificationIntentFactory();
}
public TextClassifierImpl(Context context, TextClassificationConstants settings) {
@@ -435,20 +440,16 @@
if (!expectedTypes.contains(actionType)) {
continue;
}
- List<LabeledIntent> labeledIntents =
- mTemplateIntentFactory.create(nativeSuggestion.getRemoteActionTemplates());
- Bundle extras = new Bundle();
+ LabeledIntent.Result labeledIntentResult =
+ ActionsSuggestionsHelper.createLabeledIntentResult(
+ mContext,
+ mTemplateIntentFactory,
+ nativeSuggestion);
RemoteAction remoteAction = null;
- // Given that we only support implicit intent here, we should expect there is just one
- // intent for each action type.
- if (!labeledIntents.isEmpty()) {
- LabeledIntent.TitleChooser titleChooser =
- ActionsSuggestionsHelper.createTitleChooser(actionType);
- LabeledIntent.Result result = labeledIntents.get(0).resolve(mContext, titleChooser);
- if (result != null) {
- remoteAction = result.remoteAction;
- ExtrasUtils.putActionIntent(extras, result.resolvedIntent);
- }
+ Bundle extras = new Bundle();
+ if (labeledIntentResult != null) {
+ remoteAction = labeledIntentResult.remoteAction;
+ ExtrasUtils.putActionIntent(extras, labeledIntentResult.resolvedIntent);
}
conversationActions.add(
new ConversationAction.Builder(actionType)
@@ -620,7 +621,7 @@
builder.setForeignLanguageExtra(foreignLanguageBundle);
boolean isPrimaryAction = true;
- List<LabeledIntent> labeledIntents = mIntentFactory.create(
+ List<LabeledIntent> labeledIntents = mClassificationIntentFactory.create(
mContext,
classifiedText,
foreignLanguageBundle != null,
diff --git a/core/java/android/view/textclassifier/IntentFactory.java b/core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
similarity index 92%
rename from core/java/android/view/textclassifier/IntentFactory.java
rename to core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
index 722c812..4896ae6 100644
--- a/core/java/android/view/textclassifier/IntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
+import android.view.textclassifier.TextClassifier;
import com.google.android.textclassifier.AnnotatorModel;
@@ -27,7 +28,7 @@
/**
* @hide
*/
-public interface IntentFactory {
+public interface ClassificationIntentFactory {
/**
* Return a list of LabeledIntent from the classification result.
diff --git a/core/java/android/view/textclassifier/LabeledIntent.java b/core/java/android/view/textclassifier/intent/LabeledIntent.java
similarity index 97%
rename from core/java/android/view/textclassifier/LabeledIntent.java
rename to core/java/android/view/textclassifier/intent/LabeledIntent.java
index d2897b2..4b32f1e 100644
--- a/core/java/android/view/textclassifier/LabeledIntent.java
+++ b/core/java/android/view/textclassifier/intent/LabeledIntent.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -25,6 +25,8 @@
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassification;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/view/textclassifier/LegacyIntentFactory.java b/core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
similarity index 95%
rename from core/java/android/view/textclassifier/LegacyIntentFactory.java
rename to core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
index ea9229d..1bb5430 100644
--- a/core/java/android/view/textclassifier/LegacyIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
import static java.time.temporal.ChronoUnit.MILLIS;
@@ -29,6 +29,8 @@
import android.provider.Browser;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
import com.google.android.textclassifier.AnnotatorModel;
@@ -44,13 +46,13 @@
* Creates intents based on the classification type.
* @hide
*/
-public final class LegacyIntentFactory implements IntentFactory {
+public final class LegacyClassificationIntentFactory implements ClassificationIntentFactory {
- private static final String TAG = "LegacyIntentFactory";
+ private static final String TAG = "LegacyClassificationIntentFactory";
private static final long MIN_EVENT_FUTURE_MILLIS = TimeUnit.MINUTES.toMillis(5);
private static final long DEFAULT_EVENT_DURATION = TimeUnit.HOURS.toMillis(1);
- public LegacyIntentFactory() {}
+ public LegacyClassificationIntentFactory() {}
@NonNull
@Override
@@ -96,7 +98,7 @@
break;
}
if (foreignText) {
- IntentFactory.insertTranslateAction(actions, context, text);
+ ClassificationIntentFactory.insertTranslateAction(actions, context, text);
}
actions.forEach(
action -> action.intent.putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true));
diff --git a/core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
similarity index 82%
rename from core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java
rename to core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
index ed0259f..111fc6a 100644
--- a/core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
@@ -13,14 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.google.android.textclassifier.AnnotatorModel;
@@ -36,19 +37,19 @@
* @hide
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public final class TemplateClassificationIntentFactory implements IntentFactory {
+public final class TemplateClassificationIntentFactory implements ClassificationIntentFactory {
private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
private final TemplateIntentFactory mTemplateIntentFactory;
- private final IntentFactory mFallback;
+ private final ClassificationIntentFactory mFallback;
public TemplateClassificationIntentFactory(TemplateIntentFactory templateIntentFactory,
- IntentFactory fallback) {
+ ClassificationIntentFactory fallback) {
mTemplateIntentFactory = Preconditions.checkNotNull(templateIntentFactory);
mFallback = Preconditions.checkNotNull(fallback);
}
/**
- * Returns a list of {@link android.view.textclassifier.LabeledIntent}
+ * Returns a list of {@link LabeledIntent}
* that are constructed from the classification result.
*/
@NonNull
@@ -63,15 +64,16 @@
return Collections.emptyList();
}
RemoteActionTemplate[] remoteActionTemplates = classification.getRemoteActionTemplates();
- if (ArrayUtils.isEmpty(remoteActionTemplates)) {
+ if (remoteActionTemplates == null) {
// RemoteActionTemplate is missing, fallback.
- Log.w(TAG, "RemoteActionTemplate is missing, fallback to LegacyIntentFactory.");
+ Log.w(TAG, "RemoteActionTemplate is missing, fallback to"
+ + " LegacyClassificationIntentFactory.");
return mFallback.create(context, text, foreignText, referenceTime, classification);
}
final List<LabeledIntent> labeledIntents =
mTemplateIntentFactory.create(remoteActionTemplates);
if (foreignText) {
- IntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
+ ClassificationIntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
}
return labeledIntents;
}
diff --git a/core/java/android/view/textclassifier/TemplateIntentFactory.java b/core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
similarity index 94%
rename from core/java/android/view/textclassifier/TemplateIntentFactory.java
rename to core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
index 0696d98..39e9120 100644
--- a/core/java/android/view/textclassifier/TemplateIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -21,15 +21,15 @@
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.google.android.textclassifier.NamedVariant;
import com.google.android.textclassifier.RemoteActionTemplate;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
@@ -41,11 +41,11 @@
public final class TemplateIntentFactory {
private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
- @NonNull
+ @Nullable
public List<LabeledIntent> create(
- @Nullable RemoteActionTemplate[] remoteActionTemplates) {
- if (ArrayUtils.isEmpty(remoteActionTemplates)) {
- return Collections.emptyList();
+ @NonNull RemoteActionTemplate[] remoteActionTemplates) {
+ if (remoteActionTemplates.length == 0) {
+ return new ArrayList<>();
}
final List<LabeledIntent> labeledIntents = new ArrayList<>();
for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {