Add system API to attribute source of clip data.

This adds a system API to allow the source package to be included
when clip data is set on CLipboardManager.

This is needed to ensure that the clipboard access notifications can be
properly attributed. For example, when a copy is performed through the
share sheet, the data should be attributed to the app that opened the
share sheet, not Android System.

Bug: 180577866
Test: new tests added to ClipboardManagerTest in CTS
Change-Id: Ic0ef2ea218e1dcb738b401f61cd20cd5bba6baec
This commit is contained in:
Oli Lan
2021-02-26 15:42:59 +00:00
parent 64589cc67e
commit 54c6548505
5 changed files with 106 additions and 11 deletions

View File

@@ -16,9 +16,13 @@
package android.content;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.RemoteException;
@@ -108,6 +112,31 @@ public class ClipboardManager extends android.text.ClipboardManager {
}
}
/**
* Sets the current primary clip on the clipboard, attributed to the specified {@code
* sourcePackage}. The primary clip is the clip that is involved in normal cut and paste
* operations.
*
* @param clip The clipped data item to set.
* @param sourcePackage The package name of the app that is the source of the clip data.
* @throws IllegalArgumentException if the clip is null or contains no items.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.SET_CLIP_SOURCE)
public void setPrimaryClipAsPackage(@NonNull ClipData clip, @NonNull String sourcePackage) {
try {
Objects.requireNonNull(clip);
Objects.requireNonNull(sourcePackage);
clip.prepareToLeaveProcess(true);
mService.setPrimaryClipAsPackage(
clip, mContext.getOpPackageName(), mContext.getUserId(), sourcePackage);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Clears any current primary clip on the clipboard.
*
@@ -234,6 +263,23 @@ public class ClipboardManager extends android.text.ClipboardManager {
}
}
/**
* Returns the package name of the source of the current primary clip, or null if there is no
* primary clip or if a source is not available.
*
* @hide
*/
@TestApi
@Nullable
@RequiresPermission(Manifest.permission.SET_CLIP_SOURCE)
public String getPrimaryClipSource() {
try {
return mService.getPrimaryClipSource(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@UnsupportedAppUsage
void reportPrimaryClipChanged() {
Object[] listeners;

View File

@@ -27,6 +27,8 @@ import android.content.IOnPrimaryClipChangedListener;
*/
interface IClipboard {
void setPrimaryClip(in ClipData clip, String callingPackage, int userId);
void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, int userId,
String sourcePackage);
void clearPrimaryClip(String callingPackage, int userId);
ClipData getPrimaryClip(String pkg, int userId);
ClipDescription getPrimaryClipDescription(String callingPackage, int userId);
@@ -40,4 +42,6 @@ interface IClipboard {
* Returns true if the clipboard contains text; false otherwise.
*/
boolean hasClipboardText(String callingPackage, int userId);
String getPrimaryClipSource(String callingPackage, int userId);
}