Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0984780b authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

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

parents 33c239f7 961321fe
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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) {
+19 −5
Original line number Diff line number Diff line
@@ -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
+20 −2
Original line number Diff line number Diff line
@@ -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);
@@ -588,6 +591,21 @@ public class SettingsProvider extends ContentProvider {
        final String newValue = (args == null)
                ? 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);
        values.put(Settings.NameValueTable.VALUE, newValue);
+12 −0
Original line number Diff line number Diff line
@@ -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) {
+12 −0
Original line number Diff line number Diff line
@@ -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