Merge "App ops: add op for writing settings."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0984780bc7
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user