Loading core/java/android/content/ClipboardManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -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. * * <p>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(); } Loading services/core/java/com/android/server/clipboard/ClipboardService.java +53 −11 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading @@ -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); Loading @@ -680,11 +682,51 @@ public class ClipboardService extends SystemService { } synchronized (mLock) { clip.getDescription().setConfidenceScores(confidences); PerUserClipboard clipboard = getClipboardLocked(userId); if (clipboard.primaryClip == clip) { applyClassificationAndSendBroadcastLocked( clipboard, confidences, links, classifier); // Also apply to related profiles if needed List<UserInfo> related = getRelatedProfiles(userId); if (related != null) { int size = related.size(); for (int i = 0; i < size; i++) { int id = related.get(i).id; if (id != userId) { final boolean canCopyIntoProfile = !hasRestriction( UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id); if (canCopyIntoProfile) { PerUserClipboard relatedClipboard = getClipboardLocked(id); if (hasTextLocked(relatedClipboard, text)) { applyClassificationAndSendBroadcastLocked( relatedClipboard, confidences, links, classifier); } } } } } } } } @GuardedBy("mLock") private void applyClassificationAndSendBroadcastLocked( PerUserClipboard clipboard, ArrayMap<String, Float> confidences, TextLinks links, TextClassifier classifier) { clipboard.mTextClassifier = classifier; clipboard.primaryClip.getDescription().setConfidenceScores(confidences); if (!links.getLinks().isEmpty()) { clip.getItemAt(0).setTextLinks(links); clipboard.primaryClip.getItemAt(0).setTextLinks(links); } sendClipChangedBroadcast(clipboard); } @GuardedBy("mLock") private boolean hasTextLocked(PerUserClipboard clipboard, @NonNull CharSequence text) { return clipboard.primaryClip != null && clipboard.primaryClip.getItemCount() > 0 && text.equals(clipboard.primaryClip.getItemAt(0).getText()); } private boolean isDeviceLocked(@UserIdInt int userId) { Loading Loading
core/java/android/content/ClipboardManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -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. * * <p>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(); } Loading
services/core/java/com/android/server/clipboard/ClipboardService.java +53 −11 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading @@ -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); Loading @@ -680,11 +682,51 @@ public class ClipboardService extends SystemService { } synchronized (mLock) { clip.getDescription().setConfidenceScores(confidences); PerUserClipboard clipboard = getClipboardLocked(userId); if (clipboard.primaryClip == clip) { applyClassificationAndSendBroadcastLocked( clipboard, confidences, links, classifier); // Also apply to related profiles if needed List<UserInfo> related = getRelatedProfiles(userId); if (related != null) { int size = related.size(); for (int i = 0; i < size; i++) { int id = related.get(i).id; if (id != userId) { final boolean canCopyIntoProfile = !hasRestriction( UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id); if (canCopyIntoProfile) { PerUserClipboard relatedClipboard = getClipboardLocked(id); if (hasTextLocked(relatedClipboard, text)) { applyClassificationAndSendBroadcastLocked( relatedClipboard, confidences, links, classifier); } } } } } } } } @GuardedBy("mLock") private void applyClassificationAndSendBroadcastLocked( PerUserClipboard clipboard, ArrayMap<String, Float> confidences, TextLinks links, TextClassifier classifier) { clipboard.mTextClassifier = classifier; clipboard.primaryClip.getDescription().setConfidenceScores(confidences); if (!links.getLinks().isEmpty()) { clip.getItemAt(0).setTextLinks(links); clipboard.primaryClip.getItemAt(0).setTextLinks(links); } sendClipChangedBroadcast(clipboard); } @GuardedBy("mLock") private boolean hasTextLocked(PerUserClipboard clipboard, @NonNull CharSequence text) { return clipboard.primaryClip != null && clipboard.primaryClip.getItemCount() > 0 && text.equals(clipboard.primaryClip.getItemAt(0).getText()); } private boolean isDeviceLocked(@UserIdInt int userId) { Loading