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_SEND_SMS = 20;
|
||||||
public static final int OP_READ_ICC_SMS = 21;
|
public static final int OP_READ_ICC_SMS = 21;
|
||||||
public static final int OP_WRITE_ICC_SMS = 22;
|
public static final int OP_WRITE_ICC_SMS = 22;
|
||||||
|
public static final int OP_WRITE_SETTINGS = 23;
|
||||||
/** @hide */
|
/** @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
|
* This maps each operation to the operation that serves as the
|
||||||
@@ -96,6 +97,7 @@ public class AppOpsManager {
|
|||||||
OP_WRITE_SMS,
|
OP_WRITE_SMS,
|
||||||
OP_READ_SMS,
|
OP_READ_SMS,
|
||||||
OP_WRITE_SMS,
|
OP_WRITE_SMS,
|
||||||
|
OP_WRITE_SETTINGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,6 +128,7 @@ public class AppOpsManager {
|
|||||||
"SEND_SMS",
|
"SEND_SMS",
|
||||||
"READ_ICC_SMS",
|
"READ_ICC_SMS",
|
||||||
"WRITE_ICC_SMS",
|
"WRITE_ICC_SMS",
|
||||||
|
"WRITE_SETTINGS",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,6 +159,7 @@ public class AppOpsManager {
|
|||||||
android.Manifest.permission.SEND_SMS,
|
android.Manifest.permission.SEND_SMS,
|
||||||
android.Manifest.permission.READ_SMS,
|
android.Manifest.permission.READ_SMS,
|
||||||
android.Manifest.permission.WRITE_SMS,
|
android.Manifest.permission.WRITE_SMS,
|
||||||
|
android.Manifest.permission.WRITE_SETTINGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static int opToSwitch(int op) {
|
public static int opToSwitch(int op) {
|
||||||
|
|||||||
@@ -174,8 +174,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
*/
|
*/
|
||||||
class Transport extends ContentProviderNative {
|
class Transport extends ContentProviderNative {
|
||||||
AppOpsManager mAppOpsManager = null;
|
AppOpsManager mAppOpsManager = null;
|
||||||
int mReadOp = -1;
|
int mReadOp = AppOpsManager.OP_NONE;
|
||||||
int mWriteOp = -1;
|
int mWriteOp = AppOpsManager.OP_NONE;
|
||||||
|
|
||||||
ContentProvider getContentProvider() {
|
ContentProvider getContentProvider() {
|
||||||
return ContentProvider.this;
|
return ContentProvider.this;
|
||||||
@@ -274,7 +274,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
|
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
|
@Override
|
||||||
@@ -309,7 +309,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
|
private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
|
||||||
enforceReadPermissionInner(uri);
|
enforceReadPermissionInner(uri);
|
||||||
if (mAppOpsManager != null) {
|
if (mReadOp != AppOpsManager.OP_NONE) {
|
||||||
return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
|
return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
|
||||||
}
|
}
|
||||||
return AppOpsManager.MODE_ALLOWED;
|
return AppOpsManager.MODE_ALLOWED;
|
||||||
@@ -378,7 +378,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
|
private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
|
||||||
enforceWritePermissionInner(uri);
|
enforceWritePermissionInner(uri);
|
||||||
if (mAppOpsManager != null) {
|
if (mWriteOp != AppOpsManager.OP_NONE) {
|
||||||
return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
|
return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
|
||||||
}
|
}
|
||||||
return AppOpsManager.MODE_ALLOWED;
|
return AppOpsManager.MODE_ALLOWED;
|
||||||
@@ -529,6 +529,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
mTransport.mWriteOp = writeOp;
|
mTransport.mWriteOp = writeOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public AppOpsManager getAppOpsManager() {
|
||||||
|
return mTransport.mAppOpsManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this to initialize your content provider on startup.
|
* Implement this to initialize your content provider on startup.
|
||||||
* This method is called for all registered content providers on the
|
* This method is called for all registered content providers on the
|
||||||
@@ -1188,6 +1193,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
return results;
|
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
|
* Call a provider-defined method. This can be used to implement
|
||||||
* interfaces that are cheaper and/or unnatural for a table-like
|
* 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 java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
|
import android.app.AppOpsManager;
|
||||||
import android.app.backup.BackupManager;
|
import android.app.backup.BackupManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
@@ -323,6 +324,7 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
mBackupManager = new BackupManager(getContext());
|
mBackupManager = new BackupManager(getContext());
|
||||||
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
|
setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
|
||||||
establishDbTracking(UserHandle.USER_OWNER);
|
establishDbTracking(UserHandle.USER_OWNER);
|
||||||
|
|
||||||
IntentFilter userFilter = new IntentFilter();
|
IntentFilter userFilter = new IntentFilter();
|
||||||
@@ -544,7 +546,8 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
* Fast path that avoids the use of chatty remoted Cursors.
|
* Fast path that avoids the use of chatty remoted Cursors.
|
||||||
*/
|
*/
|
||||||
@Override
|
@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();
|
int callingUser = UserHandle.getCallingUserId();
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
int reqUser = args.getInt(Settings.CALL_METHOD_USER_KEY, callingUser);
|
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
|
// Put methods - new value is in the args bundle under the key named by
|
||||||
// the Settings.NameValueTable.VALUE static.
|
// the Settings.NameValueTable.VALUE static.
|
||||||
final String newValue = (args == null)
|
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();
|
final ContentValues values = new ContentValues();
|
||||||
values.put(Settings.NameValueTable.NAME, request);
|
values.put(Settings.NameValueTable.NAME, request);
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void setMode(int code, int uid, String packageName, int mode) {
|
public void setMode(int code, int uid, String packageName, int mode) {
|
||||||
verifyIncomingUid(uid);
|
verifyIncomingUid(uid);
|
||||||
|
verifyIncomingOp(code);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, true);
|
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, true);
|
||||||
if (op != null) {
|
if (op != null) {
|
||||||
@@ -218,6 +219,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public int checkOperation(int code, int uid, String packageName) {
|
public int checkOperation(int code, int uid, String packageName) {
|
||||||
verifyIncomingUid(uid);
|
verifyIncomingUid(uid);
|
||||||
|
verifyIncomingOp(code);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
|
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
|
||||||
if (op == null) {
|
if (op == null) {
|
||||||
@@ -230,6 +232,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public int noteOperation(int code, int uid, String packageName) {
|
public int noteOperation(int code, int uid, String packageName) {
|
||||||
verifyIncomingUid(uid);
|
verifyIncomingUid(uid);
|
||||||
|
verifyIncomingOp(code);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Ops ops = getOpsLocked(uid, packageName, true);
|
Ops ops = getOpsLocked(uid, packageName, true);
|
||||||
if (ops == null) {
|
if (ops == null) {
|
||||||
@@ -261,6 +264,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public int startOperation(int code, int uid, String packageName) {
|
public int startOperation(int code, int uid, String packageName) {
|
||||||
verifyIncomingUid(uid);
|
verifyIncomingUid(uid);
|
||||||
|
verifyIncomingOp(code);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Ops ops = getOpsLocked(uid, packageName, true);
|
Ops ops = getOpsLocked(uid, packageName, true);
|
||||||
if (ops == null) {
|
if (ops == null) {
|
||||||
@@ -291,6 +295,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void finishOperation(int code, int uid, String packageName) {
|
public void finishOperation(int code, int uid, String packageName) {
|
||||||
verifyIncomingUid(uid);
|
verifyIncomingUid(uid);
|
||||||
|
verifyIncomingOp(code);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Op op = getOpLocked(code, uid, packageName, true);
|
Op op = getOpLocked(code, uid, packageName, true);
|
||||||
if (op == null) {
|
if (op == null) {
|
||||||
@@ -322,6 +327,13 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
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) {
|
private Ops getOpsLocked(int uid, String packageName, boolean edit) {
|
||||||
HashMap<String, Ops> pkgOps = mUidOps.get(uid);
|
HashMap<String, Ops> pkgOps = mUidOps.get(uid);
|
||||||
if (pkgOps == null) {
|
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
|
@Override
|
||||||
public void sendOrderedBroadcast(Intent arg0, String arg1) {
|
public void sendOrderedBroadcast(Intent arg0, String arg1) {
|
||||||
// pass
|
// 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
|
@Override
|
||||||
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
|
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
|
||||||
// pass
|
// pass
|
||||||
|
|||||||
Reference in New Issue
Block a user