Merge "App ops: adding operations for reading/writing clipboard." into jb-mr2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
305dbea8e3
@ -93,8 +93,10 @@ public class AppOpsManager {
|
|||||||
public static final int OP_CAMERA = 26;
|
public static final int OP_CAMERA = 26;
|
||||||
public static final int OP_RECORD_AUDIO = 27;
|
public static final int OP_RECORD_AUDIO = 27;
|
||||||
public static final int OP_PLAY_AUDIO = 28;
|
public static final int OP_PLAY_AUDIO = 28;
|
||||||
|
public static final int OP_READ_CLIPBOARD = 29;
|
||||||
|
public static final int OP_WRITE_CLIPBOARD = 30;
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int _NUM_OP = 29;
|
public static final int _NUM_OP = 31;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This maps each operation to the operation that serves as the
|
* This maps each operation to the operation that serves as the
|
||||||
@ -134,6 +136,8 @@ public class AppOpsManager {
|
|||||||
OP_CAMERA,
|
OP_CAMERA,
|
||||||
OP_RECORD_AUDIO,
|
OP_RECORD_AUDIO,
|
||||||
OP_PLAY_AUDIO,
|
OP_PLAY_AUDIO,
|
||||||
|
OP_READ_CLIPBOARD,
|
||||||
|
OP_WRITE_CLIPBOARD,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,6 +174,8 @@ public class AppOpsManager {
|
|||||||
"CAMERA",
|
"CAMERA",
|
||||||
"RECORD_AUDIO",
|
"RECORD_AUDIO",
|
||||||
"PLAY_AUDIO",
|
"PLAY_AUDIO",
|
||||||
|
"READ_CLIPBOARD",
|
||||||
|
"WRITE_CLIPBOARD",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,6 +212,8 @@ public class AppOpsManager {
|
|||||||
android.Manifest.permission.CAMERA,
|
android.Manifest.permission.CAMERA,
|
||||||
android.Manifest.permission.RECORD_AUDIO,
|
android.Manifest.permission.RECORD_AUDIO,
|
||||||
null, // no permission for playing audio
|
null, // no permission for playing audio
|
||||||
|
null, // no permission for reading clipboard
|
||||||
|
null, // no permission for writing clipboard
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,7 +118,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
*/
|
*/
|
||||||
public void setPrimaryClip(ClipData clip) {
|
public void setPrimaryClip(ClipData clip) {
|
||||||
try {
|
try {
|
||||||
getService().setPrimaryClip(clip);
|
getService().setPrimaryClip(clip, mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
*/
|
*/
|
||||||
public ClipData getPrimaryClip() {
|
public ClipData getPrimaryClip() {
|
||||||
try {
|
try {
|
||||||
return getService().getPrimaryClip(mContext.getPackageName());
|
return getService().getPrimaryClip(mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
*/
|
*/
|
||||||
public ClipDescription getPrimaryClipDescription() {
|
public ClipDescription getPrimaryClipDescription() {
|
||||||
try {
|
try {
|
||||||
return getService().getPrimaryClipDescription();
|
return getService().getPrimaryClipDescription(mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
*/
|
*/
|
||||||
public boolean hasPrimaryClip() {
|
public boolean hasPrimaryClip() {
|
||||||
try {
|
try {
|
||||||
return getService().hasPrimaryClip();
|
return getService().hasPrimaryClip(mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
if (mPrimaryClipChangedListeners.size() == 0) {
|
if (mPrimaryClipChangedListeners.size() == 0) {
|
||||||
try {
|
try {
|
||||||
getService().addPrimaryClipChangedListener(
|
getService().addPrimaryClipChangedListener(
|
||||||
mPrimaryClipChangedServiceListener);
|
mPrimaryClipChangedServiceListener, mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
|
|||||||
*/
|
*/
|
||||||
public boolean hasText() {
|
public boolean hasText() {
|
||||||
try {
|
try {
|
||||||
return getService().hasClipboardText();
|
return getService().hasClipboardText(mContext.getBasePackageName());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,16 @@ import android.content.IOnPrimaryClipChangedListener;
|
|||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
interface IClipboard {
|
interface IClipboard {
|
||||||
void setPrimaryClip(in ClipData clip);
|
void setPrimaryClip(in ClipData clip, String callingPackage);
|
||||||
ClipData getPrimaryClip(String pkg);
|
ClipData getPrimaryClip(String pkg);
|
||||||
ClipDescription getPrimaryClipDescription();
|
ClipDescription getPrimaryClipDescription(String callingPackage);
|
||||||
boolean hasPrimaryClip();
|
boolean hasPrimaryClip(String callingPackage);
|
||||||
void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
|
void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
|
||||||
|
String callingPackage);
|
||||||
void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
|
void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the clipboard contains text; false otherwise.
|
* Returns true if the clipboard contains text; false otherwise.
|
||||||
*/
|
*/
|
||||||
boolean hasClipboardText();
|
boolean hasClipboardText(String callingPackage);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package com.android.server;
|
|||||||
|
|
||||||
import android.app.ActivityManagerNative;
|
import android.app.ActivityManagerNative;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
|
import android.app.AppOpsManager;
|
||||||
import android.app.IActivityManager;
|
import android.app.IActivityManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
@ -55,8 +56,18 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final IActivityManager mAm;
|
private final IActivityManager mAm;
|
||||||
private final PackageManager mPm;
|
private final PackageManager mPm;
|
||||||
|
private final AppOpsManager mAppOps;
|
||||||
private final IBinder mPermissionOwner;
|
private final IBinder mPermissionOwner;
|
||||||
|
|
||||||
|
private class ListenerInfo {
|
||||||
|
final int mUid;
|
||||||
|
final String mPackageName;
|
||||||
|
ListenerInfo(int uid, String packageName) {
|
||||||
|
mUid = uid;
|
||||||
|
mPackageName = packageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class PerUserClipboard {
|
private class PerUserClipboard {
|
||||||
final int userId;
|
final int userId;
|
||||||
|
|
||||||
@ -82,6 +93,7 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mAm = ActivityManagerNative.getDefault();
|
mAm = ActivityManagerNative.getDefault();
|
||||||
mPm = context.getPackageManager();
|
mPm = context.getPackageManager();
|
||||||
|
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
IBinder permOwner = null;
|
IBinder permOwner = null;
|
||||||
try {
|
try {
|
||||||
permOwner = mAm.newUriPermissionOwner("clipboard");
|
permOwner = mAm.newUriPermissionOwner("clipboard");
|
||||||
@ -137,11 +149,15 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrimaryClip(ClipData clip) {
|
public void setPrimaryClip(ClipData clip, String callingPackage) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (clip != null && clip.getItemCount() <= 0) {
|
if (clip != null && clip.getItemCount() <= 0) {
|
||||||
throw new IllegalArgumentException("No items");
|
throw new IllegalArgumentException("No items");
|
||||||
}
|
}
|
||||||
|
if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, Binder.getCallingUid(),
|
||||||
|
callingPackage) != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
checkDataOwnerLocked(clip, Binder.getCallingUid());
|
checkDataOwnerLocked(clip, Binder.getCallingUid());
|
||||||
clearActiveOwnersLocked();
|
clearActiveOwnersLocked();
|
||||||
PerUserClipboard clipboard = getClipboard();
|
PerUserClipboard clipboard = getClipboard();
|
||||||
@ -149,7 +165,13 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
final int n = clipboard.primaryClipListeners.beginBroadcast();
|
final int n = clipboard.primaryClipListeners.beginBroadcast();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
try {
|
try {
|
||||||
clipboard.primaryClipListeners.getBroadcastItem(i).dispatchPrimaryClipChanged();
|
ListenerInfo li = (ListenerInfo)
|
||||||
|
clipboard.primaryClipListeners.getBroadcastCookie(i);
|
||||||
|
if (mAppOps.checkOpNoThrow(AppOpsManager.OP_READ_CLIPBOARD, li.mUid,
|
||||||
|
li.mPackageName) == AppOpsManager.MODE_ALLOWED) {
|
||||||
|
clipboard.primaryClipListeners.getBroadcastItem(i)
|
||||||
|
.dispatchPrimaryClipChanged();
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
|
|
||||||
// The RemoteCallbackList will take care of removing
|
// The RemoteCallbackList will take care of removing
|
||||||
@ -162,27 +184,41 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
|
|
||||||
public ClipData getPrimaryClip(String pkg) {
|
public ClipData getPrimaryClip(String pkg) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
|
||||||
|
pkg) != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
addActiveOwnerLocked(Binder.getCallingUid(), pkg);
|
addActiveOwnerLocked(Binder.getCallingUid(), pkg);
|
||||||
return getClipboard().primaryClip;
|
return getClipboard().primaryClip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClipDescription getPrimaryClipDescription() {
|
public ClipDescription getPrimaryClipDescription(String callingPackage) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
|
||||||
|
callingPackage) != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
PerUserClipboard clipboard = getClipboard();
|
PerUserClipboard clipboard = getClipboard();
|
||||||
return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null;
|
return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPrimaryClip() {
|
public boolean hasPrimaryClip(String callingPackage) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
|
||||||
|
callingPackage) != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return getClipboard().primaryClip != null;
|
return getClipboard().primaryClip != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
|
public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener,
|
||||||
|
String callingPackage) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
getClipboard().primaryClipListeners.register(listener);
|
getClipboard().primaryClipListeners.register(listener,
|
||||||
|
new ListenerInfo(Binder.getCallingUid(), callingPackage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,8 +228,12 @@ public class ClipboardService extends IClipboard.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasClipboardText() {
|
public boolean hasClipboardText(String callingPackage) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
|
||||||
|
callingPackage) != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PerUserClipboard clipboard = getClipboard();
|
PerUserClipboard clipboard = getClipboard();
|
||||||
if (clipboard.primaryClip != null) {
|
if (clipboard.primaryClip != null) {
|
||||||
CharSequence text = clipboard.primaryClip.getItemAt(0).getText();
|
CharSequence text = clipboard.primaryClip.getItemAt(0).getText();
|
||||||
|
Reference in New Issue
Block a user