Merge "TextClassifier: normalize uri for browser intent."
This commit is contained in:
committed by
Android (Google) Code Review
commit
aa0fc10c7a
@@ -85,15 +85,16 @@ public final class ExtrasUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first "translate" action found in the {@code classification} object.
|
||||
* Returns the first action found in the {@code classification} object with an intent
|
||||
* action string, {@code intentAction}.
|
||||
*/
|
||||
@Nullable
|
||||
public static RemoteAction findTranslateAction(TextClassification classification) {
|
||||
public static RemoteAction findAction(TextClassification classification, String intentAction) {
|
||||
final ArrayList<Intent> actionIntents = getActionsIntents(classification);
|
||||
if (actionIntents != null) {
|
||||
final int size = actionIntents.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (Intent.ACTION_TRANSLATE.equals(actionIntents.get(i).getAction())) {
|
||||
if (intentAction.equals(actionIntents.get(i).getAction())) {
|
||||
return classification.getActions().get(i);
|
||||
}
|
||||
}
|
||||
@@ -101,6 +102,14 @@ public final class ExtrasUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first "translate" action found in the {@code classification} object.
|
||||
*/
|
||||
@Nullable
|
||||
public static RemoteAction findTranslateAction(TextClassification classification) {
|
||||
return findAction(classification, Intent.ACTION_TRANSLATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity type contained in the {@code extra}.
|
||||
*/
|
||||
|
||||
@@ -182,7 +182,8 @@ public final class LegacyIntentFactory implements IntentFactory {
|
||||
actions.add(new LabeledIntent(
|
||||
context.getString(com.android.internal.R.string.browse),
|
||||
context.getString(com.android.internal.R.string.browse_desc),
|
||||
new Intent(Intent.ACTION_VIEW, Uri.parse(text))
|
||||
new Intent(Intent.ACTION_VIEW)
|
||||
.setDataAndNormalize(Uri.parse(text))
|
||||
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
|
||||
LabeledIntent.DEFAULT_REQUEST_CODE));
|
||||
return actions;
|
||||
|
||||
@@ -49,20 +49,18 @@ public final class TemplateIntentFactory {
|
||||
}
|
||||
final List<TextClassifierImpl.LabeledIntent> labeledIntents = new ArrayList<>();
|
||||
for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
|
||||
Intent intent = createIntent(remoteActionTemplate);
|
||||
if (intent == null) {
|
||||
if (!isValidTemplate(remoteActionTemplate)) {
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate skipped.");
|
||||
continue;
|
||||
}
|
||||
TextClassifierImpl.LabeledIntent
|
||||
labeledIntent = new TextClassifierImpl.LabeledIntent(
|
||||
remoteActionTemplate.title,
|
||||
remoteActionTemplate.description,
|
||||
intent,
|
||||
remoteActionTemplate.requestCode == null
|
||||
? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
|
||||
: remoteActionTemplate.requestCode
|
||||
);
|
||||
labeledIntents.add(labeledIntent);
|
||||
labeledIntents.add(
|
||||
new TextClassifierImpl.LabeledIntent(
|
||||
remoteActionTemplate.title,
|
||||
remoteActionTemplate.description,
|
||||
createIntent(remoteActionTemplate),
|
||||
remoteActionTemplate.requestCode == null
|
||||
? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
|
||||
: remoteActionTemplate.requestCode));
|
||||
}
|
||||
labeledIntents.forEach(
|
||||
action -> action.getIntent()
|
||||
@@ -70,29 +68,43 @@ public final class TemplateIntentFactory {
|
||||
return labeledIntents;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
|
||||
Intent intent = new Intent();
|
||||
private static boolean isValidTemplate(@Nullable RemoteActionTemplate remoteActionTemplate) {
|
||||
if (remoteActionTemplate == null) {
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate: is null");
|
||||
return false;
|
||||
}
|
||||
if (TextUtils.isEmpty(remoteActionTemplate.title)) {
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate: title is null");
|
||||
return false;
|
||||
}
|
||||
if (TextUtils.isEmpty(remoteActionTemplate.description)) {
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate: description is null");
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.isEmpty(remoteActionTemplate.packageName)) {
|
||||
Log.w(TAG, "A RemoteActionTemplate is skipped as package name is set.");
|
||||
return null;
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate: package name is set");
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.isEmpty(remoteActionTemplate.action)) {
|
||||
intent.setAction(remoteActionTemplate.action);
|
||||
}
|
||||
Uri data = null;
|
||||
if (!TextUtils.isEmpty(remoteActionTemplate.data)) {
|
||||
data = Uri.parse(remoteActionTemplate.data);
|
||||
}
|
||||
if (data != null || !TextUtils.isEmpty(remoteActionTemplate.type)) {
|
||||
intent.setDataAndType(data, remoteActionTemplate.type);
|
||||
}
|
||||
if (remoteActionTemplate.flags != null) {
|
||||
intent.setFlags(remoteActionTemplate.flags);
|
||||
if (TextUtils.isEmpty(remoteActionTemplate.action)) {
|
||||
Log.w(TAG, "Invalid RemoteActionTemplate: intent action not set");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
|
||||
final Intent intent = new Intent(remoteActionTemplate.action);
|
||||
final Uri uri = TextUtils.isEmpty(remoteActionTemplate.data)
|
||||
? null : Uri.parse(remoteActionTemplate.data).normalizeScheme();
|
||||
final String type = TextUtils.isEmpty(remoteActionTemplate.type)
|
||||
? null : Intent.normalizeMimeType(remoteActionTemplate.type);
|
||||
intent.setDataAndType(uri, type);
|
||||
intent.setFlags(remoteActionTemplate.flags == null ? 0 : remoteActionTemplate.flags);
|
||||
if (remoteActionTemplate.category != null) {
|
||||
for (String category : remoteActionTemplate.category) {
|
||||
intent.addCategory(category);
|
||||
if (category != null) {
|
||||
intent.addCategory(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
intent.putExtras(createExtras(remoteActionTemplate.extras));
|
||||
@@ -105,6 +117,9 @@ public final class TemplateIntentFactory {
|
||||
}
|
||||
Bundle bundle = new Bundle();
|
||||
for (NamedVariant namedVariant : namedVariants) {
|
||||
if (namedVariant == null) {
|
||||
continue;
|
||||
}
|
||||
switch (namedVariant.getType()) {
|
||||
case NamedVariant.TYPE_INT:
|
||||
bundle.putInt(namedVariant.getName(), namedVariant.getInt());
|
||||
|
||||
@@ -41,6 +41,7 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
|
||||
private static final String TEXT = "text";
|
||||
private static final String TITLE = "Map";
|
||||
private static final String DESCRIPTION = "Opens in Maps";
|
||||
private static final String ACTION = Intent.ACTION_VIEW;
|
||||
|
||||
@Mock
|
||||
@@ -57,19 +58,6 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
|
||||
@Test
|
||||
public void create_foreignText() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
null,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
AnnotatorModel.ClassificationResult classificationResult =
|
||||
new AnnotatorModel.ClassificationResult(
|
||||
TextClassifier.TYPE_ADDRESS,
|
||||
@@ -81,7 +69,7 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new RemoteActionTemplate[]{remoteActionTemplate});
|
||||
createRemoteActionTemplates());
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateClassificationIntentFactory.create(
|
||||
@@ -106,19 +94,6 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
|
||||
@Test
|
||||
public void create_notForeignText() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
null,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
AnnotatorModel.ClassificationResult classificationResult =
|
||||
new AnnotatorModel.ClassificationResult(
|
||||
TextClassifier.TYPE_ADDRESS,
|
||||
@@ -130,7 +105,7 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new RemoteActionTemplate[]{remoteActionTemplate});
|
||||
createRemoteActionTemplates());
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateClassificationIntentFactory.create(
|
||||
@@ -147,4 +122,21 @@ public class TemplateClassificationIntentFactoryTest {
|
||||
assertThat(intent.getAction()).isEqualTo(ACTION);
|
||||
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
|
||||
}
|
||||
|
||||
private static RemoteActionTemplate[] createRemoteActionTemplates() {
|
||||
return new RemoteActionTemplate[]{
|
||||
new RemoteActionTemplate(
|
||||
TITLE,
|
||||
DESCRIPTION,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ public class TemplateIntentFactoryTest {
|
||||
REQUEST_CODE
|
||||
);
|
||||
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
|
||||
|
||||
@@ -97,14 +96,79 @@ public class TemplateIntentFactoryTest {
|
||||
assertThat(intent.getFlags()).isEqualTo(FLAG);
|
||||
assertThat(intent.getCategories()).containsExactly((Object[]) CATEGORY);
|
||||
assertThat(intent.getPackage()).isNull();
|
||||
assertThat(
|
||||
intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
|
||||
assertThat(intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
|
||||
assertThat(intent.getIntExtra(KEY_TWO, 0)).isEqualTo(VALUE_TWO);
|
||||
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_packageIsNotNull() {
|
||||
public void normalizesScheme() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
DESCRIPTION,
|
||||
ACTION,
|
||||
"HTTp://www.android.com",
|
||||
TYPE,
|
||||
FLAG,
|
||||
CATEGORY,
|
||||
/* packageName */ null,
|
||||
NAMED_VARIANTS,
|
||||
REQUEST_CODE
|
||||
);
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
String data = intents.get(0).getIntent().getData().toString();
|
||||
assertThat(data).isEqualTo("http://www.android.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_minimal() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
DESCRIPTION,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
|
||||
|
||||
assertThat(intents).hasSize(1);
|
||||
TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
|
||||
assertThat(labeledIntent.getTitle()).isEqualTo(TITLE);
|
||||
assertThat(labeledIntent.getDescription()).isEqualTo(DESCRIPTION);
|
||||
assertThat(labeledIntent.getRequestCode()).isEqualTo(
|
||||
TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
|
||||
Intent intent = labeledIntent.getIntent();
|
||||
assertThat(intent.getAction()).isEqualTo(ACTION);
|
||||
assertThat(intent.getData()).isNull();
|
||||
assertThat(intent.getType()).isNull();
|
||||
assertThat(intent.getFlags()).isEqualTo(0);
|
||||
assertThat(intent.getCategories()).isNull();
|
||||
assertThat(intent.getPackage()).isNull();
|
||||
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidTemplate_nullTemplate() {
|
||||
RemoteActionTemplate remoteActionTemplate = null;
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
assertThat(intents).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidTemplate_nonEmptyPackageName() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
DESCRIPTION,
|
||||
@@ -121,41 +185,69 @@ public class TemplateIntentFactoryTest {
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
assertThat(intents).hasSize(0);
|
||||
assertThat(intents).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_minimal() {
|
||||
public void invalidTemplate_emptyTitle() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
null,
|
||||
DESCRIPTION,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
assertThat(intents).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidTemplate_emptyDescription() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
null,
|
||||
ACTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
assertThat(intents).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidTemplate_emptyIntentAction() {
|
||||
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
|
||||
TITLE,
|
||||
DESCRIPTION,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
List<TextClassifierImpl.LabeledIntent> intents =
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
|
||||
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
|
||||
|
||||
|
||||
assertThat(intents).hasSize(1);
|
||||
TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
|
||||
assertThat(labeledIntent.getTitle()).isNull();
|
||||
assertThat(labeledIntent.getDescription()).isNull();
|
||||
assertThat(labeledIntent.getRequestCode()).isEqualTo(
|
||||
TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
|
||||
Intent intent = labeledIntent.getIntent();
|
||||
assertThat(intent.getAction()).isNull();
|
||||
assertThat(intent.getData()).isNull();
|
||||
assertThat(intent.getType()).isNull();
|
||||
assertThat(intent.getFlags()).isEqualTo(0);
|
||||
assertThat(intent.getCategories()).isNull();
|
||||
assertThat(intent.getPackage()).isNull();
|
||||
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
|
||||
assertThat(intents).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ public class TextClassifierTest {
|
||||
|
||||
TextClassification classification = mClassifier.classifyText(request);
|
||||
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
|
||||
assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,6 +208,7 @@ public class TextClassifierTest {
|
||||
|
||||
TextClassification classification = mClassifier.classifyText(request);
|
||||
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
|
||||
assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -517,6 +519,24 @@ public class TextClassifierTest {
|
||||
};
|
||||
}
|
||||
|
||||
private static Matcher<TextClassification> containsIntentWithAction(final String action) {
|
||||
return new BaseMatcher<TextClassification>() {
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
if (o instanceof TextClassification) {
|
||||
TextClassification result = (TextClassification) o;
|
||||
return ExtrasUtils.findAction(result, action) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("intent action=").appendValue(action);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Matcher<TextLanguage> isTextLanguage(final String languageTag) {
|
||||
return new BaseMatcher<TextLanguage>() {
|
||||
@Override
|
||||
|
||||
@@ -91,8 +91,8 @@ public class TextClassifierEventTronLoggerTest {
|
||||
.isEqualTo(ConversationAction.TYPE_CALL_PHONE);
|
||||
assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
|
||||
.isWithin(0.00001f).of(0.5f);
|
||||
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME))
|
||||
.isEqualTo(EVENT_TIME);
|
||||
// Never write event time.
|
||||
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME)).isNull();
|
||||
assertThat(logMaker.getPackageName()).isEqualTo(PACKAGE_NAME);
|
||||
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_WIDGET_TYPE))
|
||||
.isEqualTo(WIDGET_TYPE);
|
||||
|
||||
Reference in New Issue
Block a user