Merge "App ops: adding operations for reading/writing clipboard." into jb-mr2-dev

This commit is contained in:
Dianne Hackborn
2013-02-26 18:16:22 +00:00
committed by Android (Google) Code Review
4 changed files with 68 additions and 19 deletions

View File

@ -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
}; };
/** /**

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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();