Merge "Add attribution tag to clipboard." into tm-qpr-dev

This commit is contained in:
Achim Thesmann
2022-07-07 17:16:35 +00:00
committed by Android (Google) Code Review
3 changed files with 168 additions and 66 deletions

View File

@@ -129,7 +129,11 @@ public class ClipboardManager extends android.text.ClipboardManager {
try { try {
Objects.requireNonNull(clip); Objects.requireNonNull(clip);
clip.prepareToLeaveProcess(true); clip.prepareToLeaveProcess(true);
mService.setPrimaryClip(clip, mContext.getOpPackageName(), mContext.getUserId()); mService.setPrimaryClip(
clip,
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -154,7 +158,11 @@ public class ClipboardManager extends android.text.ClipboardManager {
Objects.requireNonNull(sourcePackage); Objects.requireNonNull(sourcePackage);
clip.prepareToLeaveProcess(true); clip.prepareToLeaveProcess(true);
mService.setPrimaryClipAsPackage( mService.setPrimaryClipAsPackage(
clip, mContext.getOpPackageName(), mContext.getUserId(), sourcePackage); clip,
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId(),
sourcePackage);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -167,7 +175,10 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/ */
public void clearPrimaryClip() { public void clearPrimaryClip() {
try { try {
mService.clearPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); mService.clearPrimaryClip(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -183,24 +194,29 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/ */
public @Nullable ClipData getPrimaryClip() { public @Nullable ClipData getPrimaryClip() {
try { try {
return mService.getPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); return mService.getPrimaryClip(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
} }
/** /**
* Returns a description of the current primary clip on the clipboard * Returns a description of the current primary clip on the clipboard but not a copy of its
* but not a copy of its data. * data.
* *
* <em>If the application is not the default IME or does not have input focus this return * <p><em>If the application is not the default IME or does not have input focus this return
* {@code null}.</em> * {@code null}.</em>
* *
* @see #setPrimaryClip(ClipData) * @see #setPrimaryClip(ClipData)
*/ */
public @Nullable ClipDescription getPrimaryClipDescription() { public @Nullable ClipDescription getPrimaryClipDescription() {
try { try {
return mService.getPrimaryClipDescription(mContext.getOpPackageName(), return mService.getPrimaryClipDescription(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId()); mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
@@ -215,7 +231,10 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/ */
public boolean hasPrimaryClip() { public boolean hasPrimaryClip() {
try { try {
return mService.hasPrimaryClip(mContext.getOpPackageName(), mContext.getUserId()); return mService.hasPrimaryClip(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -226,7 +245,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (mPrimaryClipChangedListeners.isEmpty()) { if (mPrimaryClipChangedListeners.isEmpty()) {
try { try {
mService.addPrimaryClipChangedListener( mService.addPrimaryClipChangedListener(
mPrimaryClipChangedServiceListener, mContext.getOpPackageName(), mPrimaryClipChangedServiceListener,
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId()); mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
@@ -242,7 +263,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (mPrimaryClipChangedListeners.isEmpty()) { if (mPrimaryClipChangedListeners.isEmpty()) {
try { try {
mService.removePrimaryClipChangedListener( mService.removePrimaryClipChangedListener(
mPrimaryClipChangedServiceListener, mContext.getOpPackageName(), mPrimaryClipChangedServiceListener,
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId()); mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
@@ -280,7 +303,10 @@ public class ClipboardManager extends android.text.ClipboardManager {
@Deprecated @Deprecated
public boolean hasText() { public boolean hasText() {
try { try {
return mService.hasClipboardText(mContext.getOpPackageName(), mContext.getUserId()); return mService.hasClipboardText(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -297,7 +323,10 @@ public class ClipboardManager extends android.text.ClipboardManager {
@RequiresPermission(Manifest.permission.SET_CLIP_SOURCE) @RequiresPermission(Manifest.permission.SET_CLIP_SOURCE)
public String getPrimaryClipSource() { public String getPrimaryClipSource() {
try { try {
return mService.getPrimaryClipSource(mContext.getOpPackageName(), mContext.getUserId()); return mService.getPrimaryClipSource(
mContext.getOpPackageName(),
mContext.getAttributionTag(),
mContext.getUserId());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -26,22 +26,22 @@ import android.content.IOnPrimaryClipChangedListener;
* {@hide} * {@hide}
*/ */
interface IClipboard { interface IClipboard {
void setPrimaryClip(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, int userId, void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, String attributionTag, int userId,
String sourcePackage); String sourcePackage);
void clearPrimaryClip(String callingPackage, int userId); void clearPrimaryClip(String callingPackage, String attributionTag, int userId);
ClipData getPrimaryClip(String pkg, int userId); ClipData getPrimaryClip(String pkg, String attributionTag, int userId);
ClipDescription getPrimaryClipDescription(String callingPackage, int userId); ClipDescription getPrimaryClipDescription(String callingPackage, String attributionTag, int userId);
boolean hasPrimaryClip(String callingPackage, int userId); boolean hasPrimaryClip(String callingPackage, String attributionTag, int userId);
void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener, void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
String callingPackage, int userId); String callingPackage, String attributionTag, int userId);
void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener, void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
String callingPackage, int userId); String callingPackage, String attributionTag, int userId);
/** /**
* Returns true if the clipboard contains text; false otherwise. * 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);
} }

View File

@@ -215,9 +215,12 @@ public class ClipboardService extends SystemService {
private class ListenerInfo { private class ListenerInfo {
final int mUid; final int mUid;
final String mPackageName; final String mPackageName;
ListenerInfo(int uid, String packageName) { final String mAttributionTag;
ListenerInfo(int uid, String packageName, String attributionTag) {
mUid = uid; mUid = uid;
mPackageName = packageName; mPackageName = packageName;
mAttributionTag = attributionTag;
} }
} }
@@ -355,27 +358,43 @@ public class ClipboardService extends SystemService {
} }
@Override @Override
public void setPrimaryClip(ClipData clip, String callingPackage, @UserIdInt int userId) { public void setPrimaryClip(
checkAndSetPrimaryClip(clip, callingPackage, userId, callingPackage); ClipData clip,
String callingPackage,
String attributionTag,
@UserIdInt int userId) {
checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, callingPackage);
} }
@Override @Override
public void setPrimaryClipAsPackage( 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, getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
"Requires SET_CLIP_SOURCE permission"); "Requires SET_CLIP_SOURCE permission");
checkAndSetPrimaryClip(clip, callingPackage, userId, sourcePackage); checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, sourcePackage);
} }
private void checkAndSetPrimaryClip( 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) { if (clip == null || clip.getItemCount() <= 0) {
throw new IllegalArgumentException("No items"); throw new IllegalArgumentException("No items");
} }
final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId)) { AppOpsManager.OP_WRITE_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId)) {
return; return;
} }
checkDataOwner(clip, intendingUid); checkDataOwner(clip, intendingUid);
@@ -392,8 +411,13 @@ public class ClipboardService extends SystemService {
PROPERTY_AUTO_CLEAR_ENABLED, true)) { PROPERTY_AUTO_CLEAR_ENABLED, true)) {
mClipboardClearHandler.removeEqualMessages(ClipboardClearHandler.MSG_CLEAR, mClipboardClearHandler.removeEqualMessages(ClipboardClearHandler.MSG_CLEAR,
userId); userId);
Message clearMessage = Message.obtain(mClipboardClearHandler, Message clearMessage =
ClipboardClearHandler.MSG_CLEAR, userId, intendingUid, userId); Message.obtain(
mClipboardClearHandler,
ClipboardClearHandler.MSG_CLEAR,
userId,
intendingUid,
userId);
mClipboardClearHandler.sendMessageDelayed(clearMessage, mClipboardClearHandler.sendMessageDelayed(clearMessage,
getTimeoutForAutoClear()); getTimeoutForAutoClear());
} }
@@ -409,11 +433,16 @@ public class ClipboardService extends SystemService {
} }
@Override @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 intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId)) { AppOpsManager.OP_WRITE_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId)) {
return; return;
} }
synchronized (mLock) { synchronized (mLock) {
@@ -424,11 +453,15 @@ public class ClipboardService extends SystemService {
} }
@Override @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 intendingUid = getIntendingUid(pkg, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg, if (!clipboardAccessAllowed(
intendingUid, intendingUserId) AppOpsManager.OP_READ_CLIPBOARD,
pkg,
attributionTag,
intendingUid,
intendingUserId)
|| isDeviceLocked(intendingUserId)) { || isDeviceLocked(intendingUserId)) {
return null; return null;
} }
@@ -453,12 +486,17 @@ public class ClipboardService extends SystemService {
} }
@Override @Override
public ClipDescription getPrimaryClipDescription(String callingPackage, public ClipDescription getPrimaryClipDescription(
@UserIdInt int userId) { String callingPackage, String attributionTag, @UserIdInt int userId) {
final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId, false) AppOpsManager.OP_READ_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId,
false)
|| isDeviceLocked(intendingUserId)) { || isDeviceLocked(intendingUserId)) {
return null; return null;
} }
@@ -470,11 +508,17 @@ public class ClipboardService extends SystemService {
} }
@Override @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 intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId, false) AppOpsManager.OP_READ_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId,
false)
|| isDeviceLocked(intendingUserId)) { || isDeviceLocked(intendingUserId)) {
return false; return false;
} }
@@ -484,19 +528,28 @@ public class ClipboardService extends SystemService {
} }
@Override @Override
public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, public void addPrimaryClipChangedListener(
String callingPackage, @UserIdInt int userId) { IOnPrimaryClipChangedListener listener,
String callingPackage,
String attributionTag,
@UserIdInt int userId) {
final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
synchronized (mLock) { synchronized (mLock) {
getClipboardLocked(intendingUserId).primaryClipListeners.register(listener, getClipboardLocked(intendingUserId)
new ListenerInfo(intendingUid, callingPackage)); .primaryClipListeners
.register(
listener,
new ListenerInfo(intendingUid, callingPackage, attributionTag));
} }
} }
@Override @Override
public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, public void removePrimaryClipChangedListener(
String callingPackage, @UserIdInt int userId) { IOnPrimaryClipChangedListener listener,
String callingPackage,
String attributionTag,
@UserIdInt int userId) {
final int intendingUserId = getIntendingUserId(callingPackage, userId); final int intendingUserId = getIntendingUserId(callingPackage, userId);
synchronized (mLock) { synchronized (mLock) {
getClipboardLocked(intendingUserId).primaryClipListeners.unregister(listener); getClipboardLocked(intendingUserId).primaryClipListeners.unregister(listener);
@@ -504,11 +557,16 @@ public class ClipboardService extends SystemService {
} }
@Override @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 intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId, false) AppOpsManager.OP_READ_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId,
false)
|| isDeviceLocked(intendingUserId)) { || isDeviceLocked(intendingUserId)) {
return false; return false;
} }
@@ -523,13 +581,19 @@ public class ClipboardService extends SystemService {
} }
@Override @Override
public String getPrimaryClipSource(String callingPackage, int userId) { public String getPrimaryClipSource(
String callingPackage, String attributionTag, int userId) {
getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE, getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
"Requires SET_CLIP_SOURCE permission"); "Requires SET_CLIP_SOURCE permission");
final int intendingUid = getIntendingUid(callingPackage, userId); final int intendingUid = getIntendingUid(callingPackage, userId);
final int intendingUserId = UserHandle.getUserId(intendingUid); final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, if (!clipboardAccessAllowed(
intendingUid, intendingUserId, false) AppOpsManager.OP_READ_CLIPBOARD,
callingPackage,
attributionTag,
intendingUid,
intendingUserId,
false)
|| isDeviceLocked(intendingUserId)) { || isDeviceLocked(intendingUserId)) {
return null; return null;
} }
@@ -718,8 +782,12 @@ public class ClipboardService extends SystemService {
ListenerInfo li = (ListenerInfo) ListenerInfo li = (ListenerInfo)
clipboard.primaryClipListeners.getBroadcastCookie(i); clipboard.primaryClipListeners.getBroadcastCookie(i);
if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName, if (clipboardAccessAllowed(
li.mUid, UserHandle.getUserId(li.mUid))) { AppOpsManager.OP_READ_CLIPBOARD,
li.mPackageName,
li.mAttributionTag,
li.mUid,
UserHandle.getUserId(li.mUid))) {
clipboard.primaryClipListeners.getBroadcastItem(i) clipboard.primaryClipListeners.getBroadcastItem(i)
.dispatchPrimaryClipChanged(); .dispatchPrimaryClipChanged();
} }
@@ -965,13 +1033,18 @@ public class ClipboardService extends SystemService {
} }
} }
private boolean clipboardAccessAllowed(int op, String callingPackage, int uid, private boolean clipboardAccessAllowed(
@UserIdInt int userId) { int op, String callingPackage, String attributionTag, int uid, @UserIdInt int userId) {
return clipboardAccessAllowed(op, callingPackage, uid, userId, true); return clipboardAccessAllowed(op, callingPackage, attributionTag, uid, userId, true);
} }
private boolean clipboardAccessAllowed(int op, String callingPackage, int uid, private boolean clipboardAccessAllowed(
@UserIdInt int userId, boolean shouldNoteOp) { int op,
String callingPackage,
String attributionTag,
int uid,
@UserIdInt int userId,
boolean shouldNoteOp) {
boolean allowed; boolean allowed;
@@ -1040,7 +1113,7 @@ public class ClipboardService extends SystemService {
// Finally, check the app op. // Finally, check the app op.
int appOpsResult; int appOpsResult;
if (shouldNoteOp) { if (shouldNoteOp) {
appOpsResult = mAppOps.noteOp(op, uid, callingPackage); appOpsResult = mAppOps.noteOp(op, uid, callingPackage, attributionTag, null);
} else { } else {
appOpsResult = mAppOps.checkOp(op, uid, callingPackage); appOpsResult = mAppOps.checkOp(op, uid, callingPackage);
} }