From 0e3e509b3bf4d561c26d87213387a290dfd688e3 Mon Sep 17 00:00:00 2001 From: Achim Thesmann Date: Thu, 16 Jun 2022 04:16:33 +0000 Subject: [PATCH] Add attribution tag to clipboard. Bug: 235542330 Test: ClipboardManagerTest ClipboardAutoClearTest ClipboardManagerTest ClipboardManagerListenerTest ClipboardAccessTest ClipboardAccessTest Test: manually tested copy-paste Change-Id: I122a48a299f890ac565afb1042615edfa263b1c7 --- .../android/content/ClipboardManager.java | 55 ++++-- core/java/android/content/IClipboard.aidl | 20 +-- .../server/clipboard/ClipboardService.java | 159 +++++++++++++----- 3 files changed, 168 insertions(+), 66 deletions(-) diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index d41cda1021033..85af87722ed2e 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -129,7 +129,11 @@ public class ClipboardManager extends android.text.ClipboardManager { try { Objects.requireNonNull(clip); clip.prepareToLeaveProcess(true); - mService.setPrimaryClip(clip, mContext.getOpPackageName(), mContext.getUserId()); + mService.setPrimaryClip( + clip, + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -154,7 +158,11 @@ public class ClipboardManager extends android.text.ClipboardManager { Objects.requireNonNull(sourcePackage); clip.prepareToLeaveProcess(true); mService.setPrimaryClipAsPackage( - clip, mContext.getOpPackageName(), mContext.getUserId(), sourcePackage); + clip, + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId(), + sourcePackage); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -167,7 +175,10 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public void clearPrimaryClip() { try { - mService.clearPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); + mService.clearPrimaryClip( + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -183,24 +194,29 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public @Nullable ClipData getPrimaryClip() { try { - return mService.getPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); + return mService.getPrimaryClip( + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Returns a description of the current primary clip on the clipboard - * but not a copy of its data. + * Returns a description of the current primary clip on the clipboard but not a copy of its + * data. * - * If the application is not the default IME or does not have input focus this return + *

If the application is not the default IME or does not have input focus this return * {@code null}. * * @see #setPrimaryClip(ClipData) */ public @Nullable ClipDescription getPrimaryClipDescription() { try { - return mService.getPrimaryClipDescription(mContext.getOpPackageName(), + return mService.getPrimaryClipDescription( + mContext.getOpPackageName(), + mContext.getAttributionTag(), mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -215,7 +231,10 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public boolean hasPrimaryClip() { try { - return mService.hasPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); + return mService.hasPrimaryClip( + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -226,7 +245,9 @@ public class ClipboardManager extends android.text.ClipboardManager { if (mPrimaryClipChangedListeners.isEmpty()) { try { mService.addPrimaryClipChangedListener( - mPrimaryClipChangedServiceListener, mContext.getOpPackageName(), + mPrimaryClipChangedServiceListener, + mContext.getOpPackageName(), + mContext.getAttributionTag(), mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -242,7 +263,9 @@ public class ClipboardManager extends android.text.ClipboardManager { if (mPrimaryClipChangedListeners.isEmpty()) { try { mService.removePrimaryClipChangedListener( - mPrimaryClipChangedServiceListener, mContext.getOpPackageName(), + mPrimaryClipChangedServiceListener, + mContext.getOpPackageName(), + mContext.getAttributionTag(), mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -280,7 +303,10 @@ public class ClipboardManager extends android.text.ClipboardManager { @Deprecated public boolean hasText() { try { - return mService.hasClipboardText(mContext.getOpPackageName(), mContext.getUserId()); + return mService.hasClipboardText( + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -297,7 +323,10 @@ public class ClipboardManager extends android.text.ClipboardManager { @RequiresPermission(Manifest.permission.SET_CLIP_SOURCE) public String getPrimaryClipSource() { try { - return mService.getPrimaryClipSource(mContext.getOpPackageName(), mContext.getUserId()); + return mService.getPrimaryClipSource( + mContext.getOpPackageName(), + mContext.getAttributionTag(), + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl index 102b8e798a5cd..46ece2bc3f5ee 100644 --- a/core/java/android/content/IClipboard.aidl +++ b/core/java/android/content/IClipboard.aidl @@ -26,22 +26,22 @@ import android.content.IOnPrimaryClipChangedListener; * {@hide} */ interface IClipboard { - void setPrimaryClip(in ClipData clip, String callingPackage, int userId); - void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, int userId, + void setPrimaryClip(in ClipData clip, String callingPackage, String attributionTag, int userId); + void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, String attributionTag, int userId, String sourcePackage); - void clearPrimaryClip(String callingPackage, int userId); - ClipData getPrimaryClip(String pkg, int userId); - ClipDescription getPrimaryClipDescription(String callingPackage, int userId); - boolean hasPrimaryClip(String callingPackage, int userId); + void clearPrimaryClip(String callingPackage, String attributionTag, int userId); + ClipData getPrimaryClip(String pkg, String attributionTag, int userId); + ClipDescription getPrimaryClipDescription(String callingPackage, String attributionTag, int userId); + boolean hasPrimaryClip(String callingPackage, String attributionTag, int userId); void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener, - String callingPackage, int userId); + String callingPackage, String attributionTag, int userId); void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener, - String callingPackage, int userId); + String callingPackage, String attributionTag, int userId); /** * Returns true if the clipboard contains text; false otherwise. */ - boolean hasClipboardText(String callingPackage, int userId); + boolean hasClipboardText(String callingPackage, String attributionTag, int userId); - String getPrimaryClipSource(String callingPackage, int userId); + String getPrimaryClipSource(String callingPackage, String attributionTag, int userId); } diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 61350bb6095e9..076ac2b4bfe76 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -215,9 +215,12 @@ public class ClipboardService extends SystemService { private class ListenerInfo { final int mUid; final String mPackageName; - ListenerInfo(int uid, String packageName) { + final String mAttributionTag; + + ListenerInfo(int uid, String packageName, String attributionTag) { mUid = uid; mPackageName = packageName; + mAttributionTag = attributionTag; } } @@ -355,27 +358,43 @@ public class ClipboardService extends SystemService { } @Override - public void setPrimaryClip(ClipData clip, String callingPackage, @UserIdInt int userId) { - checkAndSetPrimaryClip(clip, callingPackage, userId, callingPackage); + public void setPrimaryClip( + ClipData clip, + String callingPackage, + String attributionTag, + @UserIdInt int userId) { + checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, callingPackage); } @Override public void setPrimaryClipAsPackage( - ClipData clip, String callingPackage, @UserIdInt int userId, String sourcePackage) { + ClipData clip, + String callingPackage, + String attributionTag, + @UserIdInt int userId, + String sourcePackage) { getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE, "Requires SET_CLIP_SOURCE permission"); - checkAndSetPrimaryClip(clip, callingPackage, userId, sourcePackage); + checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, sourcePackage); } private void checkAndSetPrimaryClip( - ClipData clip, String callingPackage, @UserIdInt int userId, String sourcePackage) { + ClipData clip, + String callingPackage, + String attributionTag, + @UserIdInt int userId, + String sourcePackage) { if (clip == null || clip.getItemCount() <= 0) { throw new IllegalArgumentException("No items"); } final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, - intendingUid, intendingUserId)) { + if (!clipboardAccessAllowed( + AppOpsManager.OP_WRITE_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId)) { return; } checkDataOwner(clip, intendingUid); @@ -392,8 +411,13 @@ public class ClipboardService extends SystemService { PROPERTY_AUTO_CLEAR_ENABLED, true)) { mClipboardClearHandler.removeEqualMessages(ClipboardClearHandler.MSG_CLEAR, userId); - Message clearMessage = Message.obtain(mClipboardClearHandler, - ClipboardClearHandler.MSG_CLEAR, userId, intendingUid, userId); + Message clearMessage = + Message.obtain( + mClipboardClearHandler, + ClipboardClearHandler.MSG_CLEAR, + userId, + intendingUid, + userId); mClipboardClearHandler.sendMessageDelayed(clearMessage, getTimeoutForAutoClear()); } @@ -409,11 +433,16 @@ public class ClipboardService extends SystemService { } @Override - public void clearPrimaryClip(String callingPackage, @UserIdInt int userId) { + public void clearPrimaryClip( + String callingPackage, String attributionTag, @UserIdInt int userId) { final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, - intendingUid, intendingUserId)) { + if (!clipboardAccessAllowed( + AppOpsManager.OP_WRITE_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId)) { return; } synchronized (mLock) { @@ -424,11 +453,15 @@ public class ClipboardService extends SystemService { } @Override - public ClipData getPrimaryClip(String pkg, @UserIdInt int userId) { + public ClipData getPrimaryClip(String pkg, String attributionTag, @UserIdInt int userId) { final int intendingUid = getIntendingUid(pkg, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg, - intendingUid, intendingUserId) + if (!clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + pkg, + attributionTag, + intendingUid, + intendingUserId) || isDeviceLocked(intendingUserId)) { return null; } @@ -453,12 +486,17 @@ public class ClipboardService extends SystemService { } @Override - public ClipDescription getPrimaryClipDescription(String callingPackage, - @UserIdInt int userId) { + public ClipDescription getPrimaryClipDescription( + String callingPackage, String attributionTag, @UserIdInt int userId) { final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) + if (!clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId, + false) || isDeviceLocked(intendingUserId)) { return null; } @@ -470,11 +508,17 @@ public class ClipboardService extends SystemService { } @Override - public boolean hasPrimaryClip(String callingPackage, @UserIdInt int userId) { + public boolean hasPrimaryClip( + String callingPackage, String attributionTag, @UserIdInt int userId) { final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) + if (!clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId, + false) || isDeviceLocked(intendingUserId)) { return false; } @@ -484,19 +528,28 @@ public class ClipboardService extends SystemService { } @Override - public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, - String callingPackage, @UserIdInt int userId) { + public void addPrimaryClipChangedListener( + IOnPrimaryClipChangedListener listener, + String callingPackage, + String attributionTag, + @UserIdInt int userId) { final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); synchronized (mLock) { - getClipboardLocked(intendingUserId).primaryClipListeners.register(listener, - new ListenerInfo(intendingUid, callingPackage)); + getClipboardLocked(intendingUserId) + .primaryClipListeners + .register( + listener, + new ListenerInfo(intendingUid, callingPackage, attributionTag)); } } @Override - public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, - String callingPackage, @UserIdInt int userId) { + public void removePrimaryClipChangedListener( + IOnPrimaryClipChangedListener listener, + String callingPackage, + String attributionTag, + @UserIdInt int userId) { final int intendingUserId = getIntendingUserId(callingPackage, userId); synchronized (mLock) { getClipboardLocked(intendingUserId).primaryClipListeners.unregister(listener); @@ -504,11 +557,16 @@ public class ClipboardService extends SystemService { } @Override - public boolean hasClipboardText(String callingPackage, int userId) { + public boolean hasClipboardText(String callingPackage, String attributionTag, int userId) { final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) + if (!clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId, + false) || isDeviceLocked(intendingUserId)) { return false; } @@ -523,13 +581,19 @@ public class ClipboardService extends SystemService { } @Override - public String getPrimaryClipSource(String callingPackage, int userId) { + public String getPrimaryClipSource( + String callingPackage, String attributionTag, int userId) { getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE, "Requires SET_CLIP_SOURCE permission"); final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) + if (!clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + callingPackage, + attributionTag, + intendingUid, + intendingUserId, + false) || isDeviceLocked(intendingUserId)) { return null; } @@ -718,8 +782,12 @@ public class ClipboardService extends SystemService { ListenerInfo li = (ListenerInfo) clipboard.primaryClipListeners.getBroadcastCookie(i); - if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName, - li.mUid, UserHandle.getUserId(li.mUid))) { + if (clipboardAccessAllowed( + AppOpsManager.OP_READ_CLIPBOARD, + li.mPackageName, + li.mAttributionTag, + li.mUid, + UserHandle.getUserId(li.mUid))) { clipboard.primaryClipListeners.getBroadcastItem(i) .dispatchPrimaryClipChanged(); } @@ -965,13 +1033,18 @@ public class ClipboardService extends SystemService { } } - private boolean clipboardAccessAllowed(int op, String callingPackage, int uid, - @UserIdInt int userId) { - return clipboardAccessAllowed(op, callingPackage, uid, userId, true); + private boolean clipboardAccessAllowed( + int op, String callingPackage, String attributionTag, int uid, @UserIdInt int userId) { + return clipboardAccessAllowed(op, callingPackage, attributionTag, uid, userId, true); } - private boolean clipboardAccessAllowed(int op, String callingPackage, int uid, - @UserIdInt int userId, boolean shouldNoteOp) { + private boolean clipboardAccessAllowed( + int op, + String callingPackage, + String attributionTag, + int uid, + @UserIdInt int userId, + boolean shouldNoteOp) { boolean allowed; @@ -1040,7 +1113,7 @@ public class ClipboardService extends SystemService { // Finally, check the app op. int appOpsResult; if (shouldNoteOp) { - appOpsResult = mAppOps.noteOp(op, uid, callingPackage); + appOpsResult = mAppOps.noteOp(op, uid, callingPackage, attributionTag, null); } else { appOpsResult = mAppOps.checkOp(op, uid, callingPackage); }