diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 11adfa3cecc0d..d41cda1021033 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -100,6 +100,10 @@ public class ClipboardManager extends android.text.ClipboardManager { /** * Callback that is invoked by {@link android.content.ClipboardManager} when the primary * clip changes. + * + *
This is called when the result of {@link ClipDescription#getClassificationStatus()}
+ * changes, as well as when new clip data is set. So in cases where text classification is
+ * performed, this callback may be invoked multiple times for the same clip.
*/
void onPrimaryClipChanged();
}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index e2aa07102ba3e..ab67b138fdbfc 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -606,6 +606,10 @@ public class ClipboardService extends SystemService {
description.setTimestamp(System.currentTimeMillis());
}
}
+ sendClipChangedBroadcast(clipboard);
+ }
+
+ private void sendClipChangedBroadcast(PerUserClipboard clipboard) {
final long ident = Binder.clearCallingIdentity();
final int n = clipboard.primaryClipListeners.beginBroadcast();
try {
@@ -615,7 +619,7 @@ public class ClipboardService extends SystemService {
clipboard.primaryClipListeners.getBroadcastCookie(i);
if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName,
- li.mUid, UserHandle.getUserId(li.mUid))) {
+ li.mUid, UserHandle.getUserId(li.mUid))) {
clipboard.primaryClipListeners.getBroadcastItem(i)
.dispatchPrimaryClipChanged();
}
@@ -632,7 +636,8 @@ public class ClipboardService extends SystemService {
@GuardedBy("mLock")
private void startClassificationLocked(@NonNull ClipData clip, @UserIdInt int userId) {
- if (clip.getItemCount() == 0) {
+ CharSequence text = (clip.getItemCount() == 0) ? null : clip.getItemAt(0).getText();
+ if (TextUtils.isEmpty(text) || text.length() > mMaxClassificationLength) {
clip.getDescription().setClassificationStatus(
ClipDescription.CLASSIFICATION_NOT_PERFORMED);
return;
@@ -650,20 +655,17 @@ public class ClipboardService extends SystemService {
} finally {
Binder.restoreCallingIdentity(ident);
}
- CharSequence text = clip.getItemAt(0).getText();
- if (TextUtils.isEmpty(text) || text.length() > mMaxClassificationLength
- || text.length() > classifier.getMaxGenerateLinksTextLength()) {
+ if (text.length() > classifier.getMaxGenerateLinksTextLength()) {
clip.getDescription().setClassificationStatus(
ClipDescription.CLASSIFICATION_NOT_PERFORMED);
return;
}
- getClipboardLocked(userId).mTextClassifier = classifier;
- mWorkerHandler.post(() -> doClassification(text, clip, classifier));
+ mWorkerHandler.post(() -> doClassification(text, clip, classifier, userId));
}
@WorkerThread
private void doClassification(
- CharSequence text, ClipData clip, TextClassifier classifier) {
+ CharSequence text, ClipData clip, TextClassifier classifier, @UserIdInt int userId) {
TextLinks.Request request = new TextLinks.Request.Builder(text).build();
TextLinks links = classifier.generateLinks(request);
@@ -680,13 +682,53 @@ public class ClipboardService extends SystemService {
}
synchronized (mLock) {
- clip.getDescription().setConfidenceScores(confidences);
- if (!links.getLinks().isEmpty()) {
- clip.getItemAt(0).setTextLinks(links);
+ PerUserClipboard clipboard = getClipboardLocked(userId);
+ if (clipboard.primaryClip == clip) {
+ applyClassificationAndSendBroadcastLocked(
+ clipboard, confidences, links, classifier);
+
+ // Also apply to related profiles if needed
+ List