summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt7
-rw-r--r--api/system-current.txt7
-rw-r--r--api/test-current.txt7
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java188
-rw-r--r--core/java/android/view/textclassifier/TextClassifierImpl.java118
-rw-r--r--core/res/res/values/strings.xml6
-rw-r--r--core/res/res/values/symbols.xml2
7 files changed, 263 insertions, 72 deletions
diff --git a/api/current.txt b/api/current.txt
index 2368231508b6..28f95c2c193c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -48630,19 +48630,26 @@ package android.view.inputmethod {
package android.view.textclassifier {
public final class TextClassification {
+ method public int getActionCount();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
+ method public android.graphics.drawable.Drawable getIcon(int);
method public android.graphics.drawable.Drawable getIcon();
+ method public android.content.Intent getIntent(int);
method public android.content.Intent getIntent();
+ method public java.lang.CharSequence getLabel(int);
method public java.lang.CharSequence getLabel();
+ method public android.view.View.OnClickListener getOnClickListener(int);
method public android.view.View.OnClickListener getOnClickListener();
method public java.lang.String getText();
}
public static final class TextClassification.Builder {
ctor public TextClassification.Builder();
+ method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener);
method public android.view.textclassifier.TextClassification build();
+ method public android.view.textclassifier.TextClassification.Builder clearActions();
method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float);
method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
diff --git a/api/system-current.txt b/api/system-current.txt
index cdd28b826179..0ec2bf7c0a97 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -52324,19 +52324,26 @@ package android.view.inputmethod {
package android.view.textclassifier {
public final class TextClassification {
+ method public int getActionCount();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
+ method public android.graphics.drawable.Drawable getIcon(int);
method public android.graphics.drawable.Drawable getIcon();
+ method public android.content.Intent getIntent(int);
method public android.content.Intent getIntent();
+ method public java.lang.CharSequence getLabel(int);
method public java.lang.CharSequence getLabel();
+ method public android.view.View.OnClickListener getOnClickListener(int);
method public android.view.View.OnClickListener getOnClickListener();
method public java.lang.String getText();
}
public static final class TextClassification.Builder {
ctor public TextClassification.Builder();
+ method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener);
method public android.view.textclassifier.TextClassification build();
+ method public android.view.textclassifier.TextClassification.Builder clearActions();
method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float);
method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
diff --git a/api/test-current.txt b/api/test-current.txt
index 90ecb8c82ceb..baf117ec99fe 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -49187,19 +49187,26 @@ package android.view.inputmethod {
package android.view.textclassifier {
public final class TextClassification {
+ method public int getActionCount();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
+ method public android.graphics.drawable.Drawable getIcon(int);
method public android.graphics.drawable.Drawable getIcon();
+ method public android.content.Intent getIntent(int);
method public android.content.Intent getIntent();
+ method public java.lang.CharSequence getLabel(int);
method public java.lang.CharSequence getLabel();
+ method public android.view.View.OnClickListener getOnClickListener(int);
method public android.view.View.OnClickListener getOnClickListener();
method public java.lang.String getText();
}
public static final class TextClassification.Builder {
ctor public TextClassification.Builder();
+ method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener);
method public android.view.textclassifier.TextClassification build();
+ method public android.view.textclassifier.TextClassification.Builder clearActions();
method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float);
method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 1849368f6ae9..8c3b8a2e6b20 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -28,6 +28,7 @@ import android.view.textclassifier.TextClassifier.EntityType;
import com.android.internal.util.Preconditions;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -41,10 +42,10 @@ public final class TextClassification {
static final TextClassification EMPTY = new TextClassification.Builder().build();
@NonNull private final String mText;
- @Nullable private final Drawable mIcon;
- @Nullable private final String mLabel;
- @Nullable private final Intent mIntent;
- @Nullable private final OnClickListener mOnClickListener;
+ @NonNull private final List<Drawable> mIcons;
+ @NonNull private final List<String> mLabels;
+ @NonNull private final List<Intent> mIntents;
+ @NonNull private final List<OnClickListener> mOnClickListeners;
@NonNull private final EntityConfidence<String> mEntityConfidence;
@NonNull private final List<String> mEntities;
private int mLogType;
@@ -52,18 +53,21 @@ public final class TextClassification {
private TextClassification(
@Nullable String text,
- @Nullable Drawable icon,
- @Nullable String label,
- @Nullable Intent intent,
- @Nullable OnClickListener onClickListener,
+ @NonNull List<Drawable> icons,
+ @NonNull List<String> labels,
+ @NonNull List<Intent> intents,
+ @NonNull List<OnClickListener> onClickListeners,
@NonNull EntityConfidence<String> entityConfidence,
int logType,
@NonNull String versionInfo) {
+ Preconditions.checkArgument(labels.size() == intents.size());
+ Preconditions.checkArgument(icons.size() == intents.size());
+ Preconditions.checkArgument(onClickListeners.size() == intents.size());
mText = text;
- mIcon = icon;
- mLabel = label;
- mIntent = intent;
- mOnClickListener = onClickListener;
+ mIcons = icons;
+ mLabels = labels;
+ mIntents = intents;
+ mOnClickListeners = onClickListeners;
mEntityConfidence = new EntityConfidence<>(entityConfidence);
mEntities = mEntityConfidence.getEntities();
mLogType = logType;
@@ -109,35 +113,106 @@ public final class TextClassification {
}
/**
- * Returns an icon that may be rendered on a widget used to act on the classified text.
+ * Returns the number of actions that are available to act on the classified text.
+ * @see #getIntent(int)
+ * @see #getLabel(int)
+ * @see #getIcon(int)
+ * @see #getOnClickListener(int)
+ */
+ @IntRange(from = 0)
+ public int getActionCount() {
+ return mIntents.size();
+ }
+
+ /**
+ * Returns one of the icons that maybe rendered on a widget used to act on the classified text.
+ * @param index Index of the action to get the icon for.
+ * @throws IndexOutOfBoundsException if the specified index is out of range.
+ * @see #getActionCount() for the number of entities available.
+ * @see #getIntent(int)
+ * @see #getLabel(int)
+ * @see #getOnClickListener(int)
+ */
+ @Nullable
+ public Drawable getIcon(int index) {
+ return mIcons.get(index);
+ }
+
+ /**
+ * Returns an icon for the default intent that may be rendered on a widget used to act on the
+ * classified text.
*/
@Nullable
public Drawable getIcon() {
- return mIcon;
+ return mIcons.isEmpty() ? null : mIcons.get(0);
}
/**
- * Returns a label that may be rendered on a widget used to act on the classified text.
+ * Returns one of the labels that may be rendered on a widget used to act on the classified
+ * text.
+ * @param index Index of the action to get the label for.
+ * @throws IndexOutOfBoundsException if the specified index is out of range.
+ * @see #getActionCount()
+ * @see #getIntent(int)
+ * @see #getIcon(int)
+ * @see #getOnClickListener(int)
+ */
+ @Nullable
+ public CharSequence getLabel(int index) {
+ return mLabels.get(index);
+ }
+
+ /**
+ * Returns a label for the default intent that may be rendered on a widget used to act on the
+ * classified text.
*/
@Nullable
public CharSequence getLabel() {
- return mLabel;
+ return mLabels.isEmpty() ? null : mLabels.get(0);
}
/**
- * Returns an intent that may be fired to act on the classified text.
+ * Returns one of the intents that may be fired to act on the classified text.
+ * @param index Index of the action to get the intent for.
+ * @throws IndexOutOfBoundsException if the specified index is out of range.
+ * @see #getActionCount()
+ * @see #getLabel(int)
+ * @see #getIcon(int)
+ * @see #getOnClickListener(int)
+ */
+ @Nullable
+ public Intent getIntent(int index) {
+ return mIntents.get(index);
+ }
+
+ /**
+ * Returns the default intent that may be fired to act on the classified text.
*/
@Nullable
public Intent getIntent() {
- return mIntent;
+ return mIntents.isEmpty() ? null : mIntents.get(0);
}
/**
- * Returns an OnClickListener that may be triggered to act on the classified text.
+ * Returns one of the OnClickListeners that may be triggered to act on the classified text.
+ * @param index Index of the action to get the click listener for.
+ * @throws IndexOutOfBoundsException if the specified index is out of range.
+ * @see #getActionCount()
+ * @see #getIntent(int)
+ * @see #getLabel(int)
+ * @see #getIcon(int)
+ */
+ @Nullable
+ public OnClickListener getOnClickListener(int index) {
+ return mOnClickListeners.get(index);
+ }
+
+ /**
+ * Returns the default OnClickListener that may be triggered to act on the classified text.
*/
@Nullable
public OnClickListener getOnClickListener() {
- return mOnClickListener;
+ return mOnClickListeners.isEmpty() ? null : mOnClickListeners.get(0);
}
/**
@@ -160,8 +235,8 @@ public final class TextClassification {
@Override
public String toString() {
return String.format("TextClassification {"
- + "text=%s, entities=%s, label=%s, intent=%s}",
- mText, mEntityConfidence, mLabel, mIntent);
+ + "text=%s, entities=%s, labels=%s, intents=%s}",
+ mText, mEntityConfidence, mLabels, mIntents);
}
/**
@@ -184,10 +259,10 @@ public final class TextClassification {
public static final class Builder {
@NonNull private String mText;
- @Nullable private Drawable mIcon;
- @Nullable private String mLabel;
- @Nullable private Intent mIntent;
- @Nullable private OnClickListener mOnClickListener;
+ @NonNull private final List<Drawable> mIcons = new ArrayList<>();
+ @NonNull private final List<String> mLabels = new ArrayList<>();
+ @NonNull private final List<Intent> mIntents = new ArrayList<>();
+ @NonNull private final List<OnClickListener> mOnClickListeners = new ArrayList<>();
@NonNull private final EntityConfidence<String> mEntityConfidence =
new EntityConfidence<>();
private int mLogType;
@@ -216,26 +291,57 @@ public final class TextClassification {
}
/**
- * Sets an icon that may be rendered on a widget used to act on the classified text.
+ * Adds an action that may be performed on the classified text. The label and icon are used
+ * for rendering of widgets that offer the intent. Actions should be added in order of
+ * priority and the first one will be treated as the default.
+ */
+ public Builder addAction(
+ Intent intent, @Nullable String label, @Nullable Drawable icon,
+ @Nullable OnClickListener onClickListener) {
+ mIntents.add(intent);
+ mLabels.add(label);
+ mIcons.add(icon);
+ mOnClickListeners.add(onClickListener);
+ return this;
+ }
+
+ /**
+ * Removes all actions.
+ */
+ public Builder clearActions() {
+ mIntents.clear();
+ mOnClickListeners.clear();
+ mLabels.clear();
+ mIcons.clear();
+ return this;
+ }
+
+ /**
+ * Sets the icon for the default action that may be rendered on a widget used to act on the
+ * classified text.
*/
public Builder setIcon(@Nullable Drawable icon) {
- mIcon = icon;
+ ensureDefaultActionAvailable();
+ mIcons.set(0, icon);
return this;
}
/**
- * Sets a label that may be rendered on a widget used to act on the classified text.
+ * Sets the label for the default action that may be rendered on a widget used to act on the
+ * classified text.
*/
public Builder setLabel(@Nullable String label) {
- mLabel = label;
+ ensureDefaultActionAvailable();
+ mLabels.set(0, label);
return this;
}
/**
- * Sets an intent that may be fired to act on the classified text.
+ * Sets the intent for the default action that may be fired to act on the classified text.
*/
public Builder setIntent(@Nullable Intent intent) {
- mIntent = intent;
+ ensureDefaultActionAvailable();
+ mIntents.set(0, intent);
return this;
}
@@ -249,10 +355,12 @@ public final class TextClassification {
}
/**
- * Sets an OnClickListener that may be triggered to act on the classified text.
+ * Sets the OnClickListener for the default action that may be triggered to act on the
+ * classified text.
*/
public Builder setOnClickListener(@Nullable OnClickListener onClickListener) {
- mOnClickListener = onClickListener;
+ ensureDefaultActionAvailable();
+ mOnClickListeners.set(0, onClickListener);
return this;
}
@@ -266,11 +374,21 @@ public final class TextClassification {
}
/**
+ * Ensures that we have at we have storage for the default action.
+ */
+ private void ensureDefaultActionAvailable() {
+ if (mIntents.isEmpty()) mIntents.add(null);
+ if (mLabels.isEmpty()) mLabels.add(null);
+ if (mIcons.isEmpty()) mIcons.add(null);
+ if (mOnClickListeners.isEmpty()) mOnClickListeners.add(null);
+ }
+
+ /**
* Builds and returns a {@link TextClassification} object.
*/
public TextClassification build() {
return new TextClassification(
- mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence,
+ mText, mIcons, mLabels, mIntents, mOnClickListeners, mEntityConfidence,
mLogType, mVersionInfo);
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 7e93b78c4809..2aa81a2ce16c 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -29,6 +29,7 @@ import android.net.Uri;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.provider.Browser;
+import android.provider.ContactsContract;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.method.WordIterator;
@@ -356,7 +357,16 @@ final class TextClassifierImpl implements TextClassifier {
final String type = getHighestScoringType(classifications);
builder.setLogType(IntentFactory.getLogType(type));
- final Intent intent = IntentFactory.create(mContext, type, text.toString());
+ final List<Intent> intents = IntentFactory.create(mContext, type, text.toString());
+ for (Intent intent : intents) {
+ extendClassificationWithIntent(intent, builder);
+ }
+
+ return builder.setVersionInfo(getVersionInfo()).build();
+ }
+
+ /** Extends the classification with the intent if it can be resolved. */
+ private void extendClassificationWithIntent(Intent intent, TextClassification.Builder builder) {
final PackageManager pm;
final ResolveInfo resolveInfo;
if (intent != null) {
@@ -367,30 +377,29 @@ final class TextClassifierImpl implements TextClassifier {
resolveInfo = null;
}
if (resolveInfo != null && resolveInfo.activityInfo != null) {
- builder.setIntent(intent)
- .setOnClickListener(TextClassification.createStartActivityOnClickListener(
- mContext, intent));
-
final String packageName = resolveInfo.activityInfo.packageName;
+ CharSequence label;
+ Drawable icon;
if ("android".equals(packageName)) {
// Requires the chooser to find an activity to handle the intent.
- builder.setLabel(IntentFactory.getLabel(mContext, type));
+ label = IntentFactory.getLabel(mContext, intent);
+ icon = null;
} else {
// A default activity will handle the intent.
intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
- Drawable icon = resolveInfo.activityInfo.loadIcon(pm);
+ icon = resolveInfo.activityInfo.loadIcon(pm);
if (icon == null) {
icon = resolveInfo.loadIcon(pm);
}
- builder.setIcon(icon);
- CharSequence label = resolveInfo.activityInfo.loadLabel(pm);
+ label = resolveInfo.activityInfo.loadLabel(pm);
if (label == null) {
label = resolveInfo.loadLabel(pm);
}
- builder.setLabel(label != null ? label.toString() : null);
}
+ builder.addAction(
+ intent, label != null ? label.toString() : null, icon,
+ TextClassification.createStartActivityOnClickListener(mContext, intent));
}
- return builder.setVersionInfo(getVersionInfo()).build();
}
private static int getHintFlags(CharSequence text, int start, int end) {
@@ -477,10 +486,11 @@ final class TextClassifierImpl implements TextClassifier {
if (results.length > 0) {
final String type = getHighestScoringType(results);
if (matches(type, linkMask)) {
- final Intent intent = IntentFactory.create(
+ // For links without disambiguation, we simply use the default intent.
+ final List<Intent> intents = IntentFactory.create(
context, type, text.substring(selectionStart, selectionEnd));
- if (hasActivityHandler(context, intent)) {
- final ClickableSpan span = createSpan(context, intent);
+ if (!intents.isEmpty() && hasActivityHandler(context, intents.get(0))) {
+ final ClickableSpan span = createSpan(context, intents.get(0));
spans.add(new SpanSpec(selectionStart, selectionEnd, span));
}
}
@@ -564,7 +574,7 @@ final class TextClassifierImpl implements TextClassifier {
};
}
- private static boolean hasActivityHandler(Context context, @Nullable Intent intent) {
+ private static boolean hasActivityHandler(Context context, Intent intent) {
if (intent == null) {
return false;
}
@@ -625,20 +635,32 @@ final class TextClassifierImpl implements TextClassifier {
private IntentFactory() {}
- @Nullable
- public static Intent create(Context context, String type, String text) {
+ @NonNull
+ public static List<Intent> create(Context context, String type, String text) {
+ final List<Intent> intents = new ArrayList<>();
type = type.trim().toLowerCase(Locale.ENGLISH);
text = text.trim();
switch (type) {
case TextClassifier.TYPE_EMAIL:
- return new Intent(Intent.ACTION_SENDTO)
- .setData(Uri.parse(String.format("mailto:%s", text)));
+ intents.add(new Intent(Intent.ACTION_SENDTO)
+ .setData(Uri.parse(String.format("mailto:%s", text))));
+ intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT)
+ .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
+ .putExtra(ContactsContract.Intents.Insert.EMAIL, text));
+ break;
case TextClassifier.TYPE_PHONE:
- return new Intent(Intent.ACTION_DIAL)
- .setData(Uri.parse(String.format("tel:%s", text)));
+ intents.add(new Intent(Intent.ACTION_DIAL)
+ .setData(Uri.parse(String.format("tel:%s", text))));
+ intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT)
+ .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
+ .putExtra(ContactsContract.Intents.Insert.PHONE, text));
+ intents.add(new Intent(Intent.ACTION_SENDTO)
+ .setData(Uri.parse(String.format("smsto:%s", text))));
+ break;
case TextClassifier.TYPE_ADDRESS:
- return new Intent(Intent.ACTION_VIEW)
- .setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
+ intents.add(new Intent(Intent.ACTION_VIEW)
+ .setData(Uri.parse(String.format("geo:0,0?q=%s", text))));
+ break;
case TextClassifier.TYPE_URL:
final String httpPrefix = "http://";
final String httpsPrefix = "https://";
@@ -649,25 +671,47 @@ final class TextClassifierImpl implements TextClassifier {
} else {
text = httpPrefix + text;
}
- return new Intent(Intent.ACTION_VIEW, Uri.parse(text))
- .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
- default:
- return null;
+ intents.add(new Intent(Intent.ACTION_VIEW, Uri.parse(text))
+ .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()));
+ break;
}
+ return intents;
}
@Nullable
- public static String getLabel(Context context, String type) {
- type = type.trim().toLowerCase(Locale.ENGLISH);
- switch (type) {
- case TextClassifier.TYPE_EMAIL:
- return context.getString(com.android.internal.R.string.email);
- case TextClassifier.TYPE_PHONE:
+ public static String getLabel(Context context, @Nullable Intent intent) {
+ if (intent == null || intent.getAction() == null) {
+ return null;
+ }
+ switch (intent.getAction()) {
+ case Intent.ACTION_DIAL:
return context.getString(com.android.internal.R.string.dial);
- case TextClassifier.TYPE_ADDRESS:
- return context.getString(com.android.internal.R.string.map);
- case TextClassifier.TYPE_URL:
- return context.getString(com.android.internal.R.string.browse);
+ case Intent.ACTION_SENDTO:
+ switch (intent.getScheme()) {
+ case "mailto":
+ return context.getString(com.android.internal.R.string.email);
+ case "smsto":
+ return context.getString(com.android.internal.R.string.sms);
+ default:
+ return null;
+ }
+ case Intent.ACTION_INSERT_OR_EDIT:
+ switch (intent.getDataString()) {
+ case ContactsContract.Contacts.CONTENT_ITEM_TYPE:
+ return context.getString(com.android.internal.R.string.add_contact);
+ default:
+ return null;
+ }
+ case Intent.ACTION_VIEW:
+ switch (intent.getScheme()) {
+ case "geo":
+ return context.getString(com.android.internal.R.string.map);
+ case "http": // fall through
+ case "https":
+ return context.getString(com.android.internal.R.string.browse);
+ default:
+ return null;
+ }
default:
return null;
}
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7416113b4e90..ea6d19c7d945 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2685,6 +2685,12 @@
<!-- Label for item in the text selection menu to trigger a Browser app [CHAR LIMIT=20] -->
<string name="browse">Browser</string>
+ <!-- Label for item in the text selection menu to trigger an SMS app [CHAR LIMIT=20] -->
+ <string name="sms">SMS</string>
+
+ <!-- Label for item in the text selection menu to trigger adding a contact [CHAR LIMIT=20] -->
+ <string name="add_contact">Contact</string>
+
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the title of that notification. -->
<string name="low_internal_storage_view_title">Storage space running out</string>
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the message of that notification. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4f03e7b06d97..77cb53abdd49 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -516,6 +516,8 @@
<java-symbol type="string" name="dial" />
<java-symbol type="string" name="map" />
<java-symbol type="string" name="browse" />
+ <java-symbol type="string" name="sms" />
+ <java-symbol type="string" name="add_contact" />
<java-symbol type="string" name="textSelectionCABTitle" />
<java-symbol type="string" name="BaMmi" />
<java-symbol type="string" name="CLIRDefaultOffNextCallOff" />