summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/textclassifier/TextClassificationManager.java98
-rw-r--r--core/java/android/widget/SelectionActionModeHelper.java21
2 files changed, 89 insertions, 30 deletions
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 1737861ee716..aee0aa719bc2 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
+import android.database.ContentObserver;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.textclassifier.TextClassifierService;
@@ -28,6 +29,8 @@ import android.view.textclassifier.TextClassifier.TextClassifierType;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import java.lang.ref.WeakReference;
+
/**
* Interface to the text classification service.
*/
@@ -42,23 +45,27 @@ public final class TextClassificationManager {
classificationContext, getTextClassifier());
private final Context mContext;
- private final TextClassificationConstants mSettings;
+ private final SettingsObserver mSettingsObserver;
@GuardedBy("mLock")
- private TextClassifier mTextClassifier;
+ @Nullable
+ private TextClassifier mCustomTextClassifier;
@GuardedBy("mLock")
+ @Nullable
private TextClassifier mLocalTextClassifier;
@GuardedBy("mLock")
+ @Nullable
private TextClassifier mSystemTextClassifier;
@GuardedBy("mLock")
private TextClassificationSessionFactory mSessionFactory;
+ @GuardedBy("mLock")
+ private TextClassificationConstants mSettings;
/** @hide */
public TextClassificationManager(Context context) {
mContext = Preconditions.checkNotNull(context);
- mSettings = TextClassificationConstants.loadFromString(Settings.Global.getString(
- context.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
mSessionFactory = mDefaultSessionFactory;
+ mSettingsObserver = new SettingsObserver(this);
}
/**
@@ -71,14 +78,13 @@ public final class TextClassificationManager {
@NonNull
public TextClassifier getTextClassifier() {
synchronized (mLock) {
- if (mTextClassifier == null) {
- if (isSystemTextClassifierEnabled()) {
- mTextClassifier = getSystemTextClassifier();
- } else {
- mTextClassifier = getLocalTextClassifier();
- }
+ if (mCustomTextClassifier != null) {
+ return mCustomTextClassifier;
+ } else if (isSystemTextClassifierEnabled()) {
+ return getSystemTextClassifier();
+ } else {
+ return getLocalTextClassifier();
}
- return mTextClassifier;
}
}
@@ -89,7 +95,7 @@ public final class TextClassificationManager {
*/
public void setTextClassifier(@Nullable TextClassifier textClassifier) {
synchronized (mLock) {
- mTextClassifier = textClassifier;
+ mCustomTextClassifier = textClassifier;
}
}
@@ -110,9 +116,15 @@ public final class TextClassificationManager {
}
}
- /** @hide */
- public TextClassificationConstants getSettings() {
- return mSettings;
+ private TextClassificationConstants getSettings() {
+ synchronized (mLock) {
+ if (mSettings == null) {
+ mSettings = TextClassificationConstants.loadFromString(Settings.Global.getString(
+ mContext.getApplicationContext().getContentResolver(),
+ Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ }
+ return mSettings;
+ }
}
/**
@@ -170,11 +182,24 @@ public final class TextClassificationManager {
}
}
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ // Note that fields could be null if the constructor threw.
+ if (mContext != null && mSettingsObserver != null) {
+ mContext.getApplicationContext().getContentResolver()
+ .unregisterContentObserver(mSettingsObserver);
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
private TextClassifier getSystemTextClassifier() {
synchronized (mLock) {
if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) {
try {
- mSystemTextClassifier = new SystemTextClassifier(mContext, mSettings);
+ mSystemTextClassifier = new SystemTextClassifier(mContext, getSettings());
Log.d(LOG_TAG, "Initialized SystemTextClassifier");
} catch (ServiceManager.ServiceNotFoundException e) {
Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e);
@@ -190,9 +215,9 @@ public final class TextClassificationManager {
private TextClassifier getLocalTextClassifier() {
synchronized (mLock) {
if (mLocalTextClassifier == null) {
- if (mSettings.isLocalTextClassifierEnabled()) {
+ if (getSettings().isLocalTextClassifierEnabled()) {
mLocalTextClassifier =
- new TextClassifierImpl(mContext, mSettings, TextClassifier.NO_OP);
+ new TextClassifierImpl(mContext, getSettings(), TextClassifier.NO_OP);
} else {
Log.d(LOG_TAG, "Local TextClassifier disabled");
mLocalTextClassifier = TextClassifier.NO_OP;
@@ -203,20 +228,51 @@ public final class TextClassificationManager {
}
private boolean isSystemTextClassifierEnabled() {
- return mSettings.isSystemTextClassifierEnabled()
+ return getSettings().isSystemTextClassifierEnabled()
&& TextClassifierService.getServiceComponentName(mContext) != null;
}
+ private void invalidate() {
+ synchronized (mLock) {
+ mSettings = null;
+ mLocalTextClassifier = null;
+ mSystemTextClassifier = null;
+ }
+ }
+
/** @hide */
public static TextClassificationConstants getSettings(Context context) {
Preconditions.checkNotNull(context);
final TextClassificationManager tcm =
context.getSystemService(TextClassificationManager.class);
if (tcm != null) {
- return tcm.mSettings;
+ return tcm.getSettings();
} else {
return TextClassificationConstants.loadFromString(Settings.Global.getString(
- context.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ context.getApplicationContext().getContentResolver(),
+ Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ }
+ }
+
+ private static final class SettingsObserver extends ContentObserver {
+
+ private final WeakReference<TextClassificationManager> mTcm;
+
+ SettingsObserver(TextClassificationManager tcm) {
+ super(null);
+ mTcm = new WeakReference<>(tcm);
+ tcm.mContext.getApplicationContext().getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.TEXT_CLASSIFIER_CONSTANTS),
+ false /* notifyForDescendants */,
+ this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ final TextClassificationManager tcm = mTcm.get();
+ if (tcm != null) {
+ tcm.invalidate();
+ }
}
}
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 1f2b90a11616..8f1f1ab2e5c0 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -70,7 +70,6 @@ public final class SelectionActionModeHelper {
private final Editor mEditor;
private final TextView mTextView;
private final TextClassificationHelper mTextClassificationHelper;
- private final TextClassificationConstants mTextClassificationSettings;
@Nullable private TextClassification mTextClassification;
private AsyncTask mTextClassificationAsyncTask;
@@ -84,7 +83,6 @@ public final class SelectionActionModeHelper {
SelectionActionModeHelper(@NonNull Editor editor) {
mEditor = Preconditions.checkNotNull(editor);
mTextView = mEditor.getTextView();
- mTextClassificationSettings = TextClassificationManager.getSettings(mTextView.getContext());
mTextClassificationHelper = new TextClassificationHelper(
mTextView.getContext(),
mTextView::getTextClassifier,
@@ -92,7 +90,7 @@ public final class SelectionActionModeHelper {
0, 1, mTextView.getTextLocales());
mSelectionTracker = new SelectionTracker(mTextView);
- if (mTextClassificationSettings.isSmartSelectionAnimationEnabled()) {
+ if (getTextClassificationSettings().isSmartSelectionAnimationEnabled()) {
mSmartSelectSprite = new SmartSelectSprite(mTextView.getContext(),
editor.getTextView().mHighlightColor, mTextView::invalidate);
} else {
@@ -105,7 +103,7 @@ public final class SelectionActionModeHelper {
*/
public void startSelectionActionModeAsync(boolean adjustSelection) {
// Check if the smart selection should run for editable text.
- adjustSelection &= mTextClassificationSettings.isSmartSelectionEnabled();
+ adjustSelection &= getTextClassificationSettings().isSmartSelectionEnabled();
mSelectionTracker.onOriginalSelection(
getText(mTextView),
@@ -212,6 +210,10 @@ public final class SelectionActionModeHelper {
return mSmartSelectSprite != null && mSmartSelectSprite.isAnimationActive();
}
+ private TextClassificationConstants getTextClassificationSettings() {
+ return TextClassificationManager.getSettings(mTextView.getContext());
+ }
+
private void cancelAsyncTask() {
if (mTextClassificationAsyncTask != null) {
mTextClassificationAsyncTask.cancel(true);
@@ -245,7 +247,7 @@ public final class SelectionActionModeHelper {
if (result != null && text instanceof Spannable
&& (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
// Do not change the selection if TextClassifier should be dark launched.
- if (!mTextClassificationSettings.isModelDarkLaunchEnabled()) {
+ if (!getTextClassificationSettings().isModelDarkLaunchEnabled()) {
Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
mTextView.invalidate();
}
@@ -906,7 +908,6 @@ public final class SelectionActionModeHelper {
private static final int TRIM_DELTA = 120; // characters
private final Context mContext;
- private final boolean mDarkLaunchEnabled;
private Supplier<TextClassifier> mTextClassifier;
/** The original TextView text. **/
@@ -942,8 +943,6 @@ public final class SelectionActionModeHelper {
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
init(textClassifier, text, selectionStart, selectionEnd, locales);
mContext = Preconditions.checkNotNull(context);
- mDarkLaunchEnabled = TextClassificationManager.getSettings(mContext)
- .isModelDarkLaunchEnabled();
}
@UiThread
@@ -982,7 +981,7 @@ public final class SelectionActionModeHelper {
mTrimmedText, mRelativeStart, mRelativeEnd, mDefaultLocales);
}
// Do not classify new selection boundaries if TextClassifier should be dark launched.
- if (!mDarkLaunchEnabled) {
+ if (!isDarkLaunchEnabled()) {
mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart);
mSelectionEnd = Math.min(
mText.length(), selection.getSelectionEndIndex() + mTrimStart);
@@ -1010,6 +1009,10 @@ public final class SelectionActionModeHelper {
}
}
+ private boolean isDarkLaunchEnabled() {
+ return TextClassificationManager.getSettings(mContext).isModelDarkLaunchEnabled();
+ }
+
private SelectionResult performClassification(@Nullable TextSelection selection) {
if (!Objects.equals(mText, mLastClassificationText)
|| mSelectionStart != mLastClassificationSelectionStart