Loading core/java/android/provider/Settings.java +16 −0 Original line number Diff line number Diff line Loading @@ -9543,6 +9543,22 @@ public final class Settings { */ public static final String DEVICE_POLICY_CONSTANTS = "device_policy_constants"; /** * TextClassifier specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * <pre> * smart_selection_dark_launch (boolean) * smart_selection_enabled_for_edit_text (boolean) * </pre> * * <p> * Type: string * @hide * see also android.view.textclassifier.TextClassifierConstants */ public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants"; /** * Get the key that retrieves a bluetooth headset's priority. * @hide Loading core/java/android/view/textclassifier/TextClassifier.java +8 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,12 @@ public interface TextClassifier { */ @WorkerThread default void logEvent(String source, String event) {} /** * Returns this TextClassifier's settings. * @hide */ default TextClassifierConstants getSettings() { return TextClassifierConstants.DEFAULT; } } core/java/android/view/textclassifier/TextClassifierConstants.java 0 → 100644 +90 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.Nullable; import android.util.KeyValueListParser; import android.util.Slog; /** * TextClassifier specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * <pre> * smart_selection_dark_launch (boolean) * smart_selection_enabled_for_edit_text (boolean) * </pre> * * <p> * Type: string * see also android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS * * Example of setting the values for testing. * adb shell settings put global text_classifier_constants smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true * @hide */ public final class TextClassifierConstants { private static final String LOG_TAG = "TextClassifierConstants"; private static final String SMART_SELECTION_DARK_LAUNCH = "smart_selection_dark_launch"; private static final String SMART_SELECTION_ENABLED_FOR_EDIT_TEXT = "smart_selection_enabled_for_edit_text"; private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false; private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true; /** Default settings. */ static final TextClassifierConstants DEFAULT = new TextClassifierConstants(); private final boolean mDarkLaunch; private final boolean mSuggestSelectionEnabledForEditableText; private TextClassifierConstants() { mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT; mSuggestSelectionEnabledForEditableText = SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT; } private TextClassifierConstants(@Nullable String settings) { final KeyValueListParser parser = new KeyValueListParser(','); try { parser.setString(settings); } catch (IllegalArgumentException e) { // Failed to parse the settings string, log this and move on with defaults. Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings); } mDarkLaunch = parser.getBoolean( SMART_SELECTION_DARK_LAUNCH, SMART_SELECTION_DARK_LAUNCH_DEFAULT); mSuggestSelectionEnabledForEditableText = parser.getBoolean( SMART_SELECTION_ENABLED_FOR_EDIT_TEXT, SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT); } static TextClassifierConstants loadFromString(String settings) { return new TextClassifierConstants(settings); } public boolean isDarkLaunch() { return mDarkLaunch; } public boolean isSuggestSelectionEnabledForEditableText() { return mSuggestSelectionEnabledForEditableText; } } core/java/android/view/textclassifier/TextClassifierImpl.java +13 −1 Original line number Diff line number Diff line Loading @@ -24,11 +24,11 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.icu.text.BreakIterator; import android.net.Uri; import android.os.LocaleList; import android.os.ParcelFileDescriptor; import android.provider.Browser; import android.provider.Settings; import android.text.Spannable; import android.text.TextUtils; import android.text.method.WordIterator; Loading @@ -46,6 +46,7 @@ import com.android.internal.util.Preconditions; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.BreakIterator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; Loading Loading @@ -90,6 +91,8 @@ final class TextClassifierImpl implements TextClassifier { @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. private SmartSelection mSmartSelection; private TextClassifierConstants mSettings; TextClassifierImpl(Context context) { mContext = Preconditions.checkNotNull(context); } Loading Loading @@ -188,6 +191,15 @@ final class TextClassifierImpl implements TextClassifier { } } @Override public TextClassifierConstants getSettings() { if (mSettings == null) { mSettings = TextClassifierConstants.loadFromString(Settings.Global.getString( mContext.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS)); } return mSettings; } private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException { synchronized (mSmartSelectionLock) { localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList; Loading core/java/android/widget/SelectionActionModeHelper.java +20 −10 Original line number Diff line number Diff line Loading @@ -71,11 +71,15 @@ final class SelectionActionModeHelper { } public void startActionModeAsync(boolean adjustSelection) { // Check if the smart selection should run for editable text. adjustSelection &= !mTextView.isTextEditable() || mTextView.getTextClassifier().getSettings() .isSuggestSelectionEnabledForEditableText(); mSelectionTracker.onOriginalSelection( getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextView.isTextEditable()); mTextView.getSelectionEnd()); cancelAsyncTask(); if (skipTextClassification()) { startActionMode(null); Loading Loading @@ -163,7 +167,10 @@ final class SelectionActionModeHelper { private void startActionMode(@Nullable SelectionResult result) { final CharSequence text = getText(mTextView); if (result != null && text instanceof Spannable) { // Do not change the selection if TextClassifier should be dark launched. if (!mTextView.getTextClassifier().getSettings().isDarkLaunch()) { Selection.setSelection((Spannable) text, result.mStart, result.mEnd); } mTextClassification = result.mClassification; } else { mTextClassification = null; Loading Loading @@ -193,7 +200,7 @@ final class SelectionActionModeHelper { } private void resetTextClassificationHelper() { mTextClassificationHelper.reset( mTextClassificationHelper.init( mTextView.getTextClassifier(), getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), Loading Loading @@ -225,8 +232,7 @@ final class SelectionActionModeHelper { /** * Called when the original selection happens, before smart selection is triggered. */ public void onOriginalSelection( CharSequence text, int selectionStart, int selectionEnd, boolean editableText) { public void onOriginalSelection(CharSequence text, int selectionStart, int selectionEnd) { // If we abandoned a selection and created a new one very shortly after, we may still // have a pending request to log ABANDON, which we flush here. mDelayedLogAbandon.flush(); Loading Loading @@ -622,11 +628,11 @@ final class SelectionActionModeHelper { TextClassificationHelper(TextClassifier textClassifier, CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { reset(textClassifier, text, selectionStart, selectionEnd, locales); init(textClassifier, text, selectionStart, selectionEnd, locales); } @UiThread public void reset(TextClassifier textClassifier, public void init(TextClassifier textClassifier, CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { mTextClassifier = Preconditions.checkNotNull(textClassifier); mText = Preconditions.checkNotNull(text).toString(); Loading @@ -649,8 +655,12 @@ final class SelectionActionModeHelper { trimText(); final TextSelection selection = mTextClassifier.suggestSelection( mTrimmedText, mRelativeStart, mRelativeEnd, mLocales); // Do not classify new selection boundaries if TextClassifier should be dark launched. if (!mTextClassifier.getSettings().isDarkLaunch()) { mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart); mSelectionEnd = Math.min(mText.length(), selection.getSelectionEndIndex() + mTrimStart); mSelectionEnd = Math.min( mText.length(), selection.getSelectionEndIndex() + mTrimStart); } return performClassification(selection); } Loading Loading
core/java/android/provider/Settings.java +16 −0 Original line number Diff line number Diff line Loading @@ -9543,6 +9543,22 @@ public final class Settings { */ public static final String DEVICE_POLICY_CONSTANTS = "device_policy_constants"; /** * TextClassifier specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * <pre> * smart_selection_dark_launch (boolean) * smart_selection_enabled_for_edit_text (boolean) * </pre> * * <p> * Type: string * @hide * see also android.view.textclassifier.TextClassifierConstants */ public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants"; /** * Get the key that retrieves a bluetooth headset's priority. * @hide Loading
core/java/android/view/textclassifier/TextClassifier.java +8 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,12 @@ public interface TextClassifier { */ @WorkerThread default void logEvent(String source, String event) {} /** * Returns this TextClassifier's settings. * @hide */ default TextClassifierConstants getSettings() { return TextClassifierConstants.DEFAULT; } }
core/java/android/view/textclassifier/TextClassifierConstants.java 0 → 100644 +90 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.Nullable; import android.util.KeyValueListParser; import android.util.Slog; /** * TextClassifier specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * <pre> * smart_selection_dark_launch (boolean) * smart_selection_enabled_for_edit_text (boolean) * </pre> * * <p> * Type: string * see also android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS * * Example of setting the values for testing. * adb shell settings put global text_classifier_constants smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true * @hide */ public final class TextClassifierConstants { private static final String LOG_TAG = "TextClassifierConstants"; private static final String SMART_SELECTION_DARK_LAUNCH = "smart_selection_dark_launch"; private static final String SMART_SELECTION_ENABLED_FOR_EDIT_TEXT = "smart_selection_enabled_for_edit_text"; private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false; private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true; /** Default settings. */ static final TextClassifierConstants DEFAULT = new TextClassifierConstants(); private final boolean mDarkLaunch; private final boolean mSuggestSelectionEnabledForEditableText; private TextClassifierConstants() { mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT; mSuggestSelectionEnabledForEditableText = SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT; } private TextClassifierConstants(@Nullable String settings) { final KeyValueListParser parser = new KeyValueListParser(','); try { parser.setString(settings); } catch (IllegalArgumentException e) { // Failed to parse the settings string, log this and move on with defaults. Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings); } mDarkLaunch = parser.getBoolean( SMART_SELECTION_DARK_LAUNCH, SMART_SELECTION_DARK_LAUNCH_DEFAULT); mSuggestSelectionEnabledForEditableText = parser.getBoolean( SMART_SELECTION_ENABLED_FOR_EDIT_TEXT, SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT); } static TextClassifierConstants loadFromString(String settings) { return new TextClassifierConstants(settings); } public boolean isDarkLaunch() { return mDarkLaunch; } public boolean isSuggestSelectionEnabledForEditableText() { return mSuggestSelectionEnabledForEditableText; } }
core/java/android/view/textclassifier/TextClassifierImpl.java +13 −1 Original line number Diff line number Diff line Loading @@ -24,11 +24,11 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.icu.text.BreakIterator; import android.net.Uri; import android.os.LocaleList; import android.os.ParcelFileDescriptor; import android.provider.Browser; import android.provider.Settings; import android.text.Spannable; import android.text.TextUtils; import android.text.method.WordIterator; Loading @@ -46,6 +46,7 @@ import com.android.internal.util.Preconditions; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.BreakIterator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; Loading Loading @@ -90,6 +91,8 @@ final class TextClassifierImpl implements TextClassifier { @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. private SmartSelection mSmartSelection; private TextClassifierConstants mSettings; TextClassifierImpl(Context context) { mContext = Preconditions.checkNotNull(context); } Loading Loading @@ -188,6 +191,15 @@ final class TextClassifierImpl implements TextClassifier { } } @Override public TextClassifierConstants getSettings() { if (mSettings == null) { mSettings = TextClassifierConstants.loadFromString(Settings.Global.getString( mContext.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS)); } return mSettings; } private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException { synchronized (mSmartSelectionLock) { localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList; Loading
core/java/android/widget/SelectionActionModeHelper.java +20 −10 Original line number Diff line number Diff line Loading @@ -71,11 +71,15 @@ final class SelectionActionModeHelper { } public void startActionModeAsync(boolean adjustSelection) { // Check if the smart selection should run for editable text. adjustSelection &= !mTextView.isTextEditable() || mTextView.getTextClassifier().getSettings() .isSuggestSelectionEnabledForEditableText(); mSelectionTracker.onOriginalSelection( getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextView.isTextEditable()); mTextView.getSelectionEnd()); cancelAsyncTask(); if (skipTextClassification()) { startActionMode(null); Loading Loading @@ -163,7 +167,10 @@ final class SelectionActionModeHelper { private void startActionMode(@Nullable SelectionResult result) { final CharSequence text = getText(mTextView); if (result != null && text instanceof Spannable) { // Do not change the selection if TextClassifier should be dark launched. if (!mTextView.getTextClassifier().getSettings().isDarkLaunch()) { Selection.setSelection((Spannable) text, result.mStart, result.mEnd); } mTextClassification = result.mClassification; } else { mTextClassification = null; Loading Loading @@ -193,7 +200,7 @@ final class SelectionActionModeHelper { } private void resetTextClassificationHelper() { mTextClassificationHelper.reset( mTextClassificationHelper.init( mTextView.getTextClassifier(), getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), Loading Loading @@ -225,8 +232,7 @@ final class SelectionActionModeHelper { /** * Called when the original selection happens, before smart selection is triggered. */ public void onOriginalSelection( CharSequence text, int selectionStart, int selectionEnd, boolean editableText) { public void onOriginalSelection(CharSequence text, int selectionStart, int selectionEnd) { // If we abandoned a selection and created a new one very shortly after, we may still // have a pending request to log ABANDON, which we flush here. mDelayedLogAbandon.flush(); Loading Loading @@ -622,11 +628,11 @@ final class SelectionActionModeHelper { TextClassificationHelper(TextClassifier textClassifier, CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { reset(textClassifier, text, selectionStart, selectionEnd, locales); init(textClassifier, text, selectionStart, selectionEnd, locales); } @UiThread public void reset(TextClassifier textClassifier, public void init(TextClassifier textClassifier, CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { mTextClassifier = Preconditions.checkNotNull(textClassifier); mText = Preconditions.checkNotNull(text).toString(); Loading @@ -649,8 +655,12 @@ final class SelectionActionModeHelper { trimText(); final TextSelection selection = mTextClassifier.suggestSelection( mTrimmedText, mRelativeStart, mRelativeEnd, mLocales); // Do not classify new selection boundaries if TextClassifier should be dark launched. if (!mTextClassifier.getSettings().isDarkLaunch()) { mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart); mSelectionEnd = Math.min(mText.length(), selection.getSelectionEndIndex() + mTrimStart); mSelectionEnd = Math.min( mText.length(), selection.getSelectionEndIndex() + mTrimStart); } return performClassification(selection); } Loading