Merge "App ops: add op for writing settings."

This commit is contained in:
Dianne Hackborn
2013-02-06 01:34:40 +00:00
committed by Android (Google) Code Review
5 changed files with 68 additions and 8 deletions

View File

@@ -61,8 +61,9 @@ public class AppOpsManager {
public static final int OP_SEND_SMS = 20;
public static final int OP_READ_ICC_SMS = 21;
public static final int OP_WRITE_ICC_SMS = 22;
public static final int OP_WRITE_SETTINGS = 23;
/** @hide */
public static final int _NUM_OP = 23;
public static final int _NUM_OP = 24;
/**
* This maps each operation to the operation that serves as the
@@ -96,6 +97,7 @@ public class AppOpsManager {
OP_WRITE_SMS,
OP_READ_SMS,
OP_WRITE_SMS,
OP_WRITE_SETTINGS,
};
/**
@@ -126,6 +128,7 @@ public class AppOpsManager {
"SEND_SMS",
"READ_ICC_SMS",
"WRITE_ICC_SMS",
"WRITE_SETTINGS",
};
/**
@@ -156,6 +159,7 @@ public class AppOpsManager {
android.Manifest.permission.SEND_SMS,
android.Manifest.permission.READ_SMS,
android.Manifest.permission.WRITE_SMS,
android.Manifest.permission.WRITE_SETTINGS,
};
public static int opToSwitch(int op) {

View File

@@ -174,8 +174,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*/
class Transport extends ContentProviderNative {
AppOpsManager mAppOpsManager = null;
int mReadOp = -1;
int mWriteOp = -1;
int mReadOp = AppOpsManager.OP_NONE;
int mWriteOp = AppOpsManager.OP_NONE;
ContentProvider getContentProvider() {
return ContentProvider.this;
@@ -274,7 +274,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
return ContentProvider.this.call(method, arg, extras);
return ContentProvider.this.callFromPackage(callingPkg, method, arg, extras);
}
@Override
@@ -309,7 +309,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
enforceReadPermissionInner(uri);
if (mAppOpsManager != null) {
if (mReadOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
}
return AppOpsManager.MODE_ALLOWED;
@@ -378,7 +378,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
enforceWritePermissionInner(uri);
if (mAppOpsManager != null) {
if (mWriteOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
}
return AppOpsManager.MODE_ALLOWED;
@@ -529,6 +529,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
mTransport.mWriteOp = writeOp;
}
/** @hide */
public AppOpsManager getAppOpsManager() {
return mTransport.mAppOpsManager;
}
/**
* Implement this to initialize your content provider on startup.
* This method is called for all registered content providers on the
@@ -1188,6 +1193,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return results;
}
/**
* @hide
* Front-end to {@link #call(String, String, android.os.Bundle)} that provides the name
* of the calling package.
*/
public Bundle callFromPackage(String callingPackag, String method, String arg, Bundle extras) {
return call(method, arg, extras);
}
/**
* Call a provider-defined method. This can be used to implement
* interfaces that are cheaper and/or unnatural for a table-like

View File

@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
@@ -323,6 +324,7 @@ public class SettingsProvider extends ContentProvider {
mBackupManager = new BackupManager(getContext());
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
establishDbTracking(UserHandle.USER_OWNER);
IntentFilter userFilter = new IntentFilter();
@@ -544,7 +546,8 @@ public class SettingsProvider extends ContentProvider {
* Fast path that avoids the use of chatty remoted Cursors.
*/
@Override
public Bundle call(String method, String request, Bundle args) {
public Bundle callFromPackage(String callingPackage, String method, String request,
Bundle args) {
int callingUser = UserHandle.getCallingUserId();
if (args != null) {
int reqUser = args.getInt(Settings.CALL_METHOD_USER_KEY, callingUser);
@@ -586,7 +589,22 @@ public class SettingsProvider extends ContentProvider {
// Put methods - new value is in the args bundle under the key named by
// the Settings.NameValueTable.VALUE static.
final String newValue = (args == null)
? null : args.getString(Settings.NameValueTable.VALUE);
? null : args.getString(Settings.NameValueTable.VALUE);
// Framework can't do automatic permission checking for calls, so we need
// to do it here.
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
String.format("Permission denial: writing to settings requires %1$s",
android.Manifest.permission.WRITE_SETTINGS));
}
// Also need to take care of app op.
if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SETTINGS, Binder.getCallingUid(),
callingPackage) != AppOpsManager.MODE_ALLOWED) {
return null;
}
final ContentValues values = new ContentValues();
values.put(Settings.NameValueTable.NAME, request);

View File

@@ -204,6 +204,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public void setMode(int code, int uid, String packageName, int mode) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, true);
if (op != null) {
@@ -218,6 +219,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int checkOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
if (op == null) {
@@ -230,6 +232,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int noteOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
@@ -261,6 +264,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int startOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
@@ -291,6 +295,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public void finishOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
Op op = getOpLocked(code, uid, packageName, true);
if (op == null) {
@@ -322,6 +327,13 @@ public class AppOpsService extends IAppOpsService.Stub {
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
private void verifyIncomingOp(int op) {
if (op >= 0 && op < AppOpsManager._NUM_OP) {
return;
}
throw new IllegalArgumentException("Bad operation #" + op);
}
private Ops getOpsLocked(int uid, String packageName, boolean edit) {
HashMap<String, Ops> pkgOps = mUidOps.get(uid);
if (pkgOps == null) {

View File

@@ -1205,6 +1205,11 @@ public final class BridgeContext extends Context {
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
// pass
}
@Override
public void sendOrderedBroadcast(Intent arg0, String arg1) {
// pass
@@ -1219,6 +1224,13 @@ public final class BridgeContext extends Context {
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
// pass
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
// pass