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

Commit 948e1317 authored by Shashank Mittal's avatar Shashank Mittal Committed by Ricardo Cerqueira
Browse files

AppOps: Add support for AppOps policy file

Add support to read AppOps policy file.
AppOps policy file can be used to configure Ops default policy.

Change-Id: Idb4e3501ff9f58e491b06e74152342aa9574afbf
parent 8b8457f6
Loading
Loading
Loading
Loading
+248 −1
Original line number Diff line number Diff line
@@ -114,7 +114,8 @@ public class AppOpsManager {

    // when adding one of these:
    //  - increment _NUM_OP
    //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode, sOpDefaultStrictMode
    //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode, sOpDefaultStrictMode,
    //    sOpToOpString, sOpStrictMode.
    //  - add descriptive strings to frameworks/base/core/res/res/values/config.xml
    //  - add descriptive strings to Settings/res/values/arrays.xml
    //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
@@ -239,6 +240,91 @@ public class AppOpsManager {
    @SystemApi
    public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";

    private static final String OPSTR_GPS =
            "android:gps";
    private static final String OPSTR_VIBRATE =
            "android:vibrate";
    private static final String OPSTR_READ_CONTACTS =
            "android:read_contacts";
    private static final String OPSTR_WRITE_CONTACTS =
            "android:write_contacts";
    private static final String OPSTR_READ_CALL_LOG =
            "android:read_call_log";
    private static final String OPSTR_WRITE_CALL_LOG =
            "android:write_call_log";
    private static final String OPSTR_READ_CALENDAR =
            "android:read_calendar";
    private static final String OPSTR_WRITE_CALENDAR =
            "android:write_calendar";
    private static final String OPSTR_WIFI_SCAN =
            "android:wifi_scan";
    private static final String OPSTR_POST_NOTIFICATION =
            "android:post_notification";
    private static final String OPSTR_NEIGHBORING_CELLS =
            "android:neighboring_cells";
    private static final String OPSTR_CALL_PHONE =
            "android:call_phone";
    private static final String OPSTR_READ_SMS =
            "android:read_sms";
    private static final String OPSTR_WRITE_SMS =
            "android:write_sms";
    private static final String OPSTR_RECEIVE_SMS =
            "android:receive_sms";
    private static final String OPSTR_RECEIVE_EMERGECY_SMS =
            "android:receive_emergecy_sms";
    private static final String OPSTR_RECEIVE_MMS =
            "android:receive_mms";
    private static final String OPSTR_RECEIVE_WAP_PUSH =
            "android:receive_wap_push";
    private static final String OPSTR_SEND_SMS =
            "android:send_sms";
    private static final String OPSTR_READ_ICC_SMS =
            "android:read_icc_sms";
    private static final String OPSTR_WRITE_ICC_SMS =
            "android:write_icc_sms";
    private static final String OPSTR_WRITE_SETTINGS =
            "android:write_settings";
    private static final String OPSTR_SYSTEM_ALERT_WINDOW =
            "android:system_alert_window";
    private static final String OPSTR_ACCESS_NOTIFICATIONS =
            "android:access_notifications";
    private static final String OPSTR_CAMERA =
            "android:camera";
    private static final String OPSTR_RECORD_AUDIO =
            "android:record_audio";
    private static final String OPSTR_PLAY_AUDIO =
            "android:play_audio";
    private static final String OPSTR_READ_CLIPBOARD =
            "android:read_clipboard";
    private static final String OPSTR_WRITE_CLIPBOARD =
            "android:write_clipboard";
    private static final String OPSTR_TAKE_MEDIA_BUTTONS =
            "android:take_media_buttons";
    private static final String OPSTR_TAKE_AUDIO_FOCUS =
            "android:take_audio_focus";
    private static final String OPSTR_AUDIO_MASTER_VOLUME =
            "android:audio_master_volume";
    private static final String OPSTR_AUDIO_VOICE_VOLUME =
            "android:audio_voice_volume";
    private static final String OPSTR_AUDIO_RING_VOLUME =
            "android:audio_ring_volume";
    private static final String OPSTR_AUDIO_MEDIA_VOLUME =
            "android:audio_media_volume";
    private static final String OPSTR_AUDIO_ALARM_VOLUME =
            "android:audio_alarm_volume";
    private static final String OPSTR_AUDIO_NOTIFICATION_VOLUME =
            "android:audio_notification_volume";
    private static final String OPSTR_AUDIO_BLUETOOTH_VOLUME =
            "android:audio_bluetooth_volume";
    private static final String OPSTR_WAKE_LOCK =
            "android:wake_lock";
    private static final String OPSTR_MUTE_MICROPHONE =
            "android:mute_microphone";
    private static final String OPSTR_TOAST_WINDOW =
            "android:toast_window";
    private static final String OPSTR_PROJECT_MEDIA =
            "android:project_media";

    /**
     * This maps each operation to the operation that serves as the
     * switch to determine whether it is allowed.  Generally this is
@@ -353,6 +439,61 @@ public class AppOpsManager {
            OPSTR_ACTIVATE_VPN,
    };

    /**
     * This maps each operation to the public string constant for it.
     * If it doesn't have a public string constant, it maps to null.
     */
    private static String[] sOpToOpString = new String[] {
        OPSTR_COARSE_LOCATION,
        OPSTR_FINE_LOCATION,
        OPSTR_GPS,
        OPSTR_VIBRATE,
        OPSTR_READ_CONTACTS,
        OPSTR_WRITE_CONTACTS,
        OPSTR_READ_CALL_LOG,
        OPSTR_WRITE_CALL_LOG,
        OPSTR_READ_CALENDAR,
        OPSTR_WRITE_CALENDAR,
        OPSTR_WIFI_SCAN,
        OPSTR_POST_NOTIFICATION,
        OPSTR_NEIGHBORING_CELLS,
        OPSTR_CALL_PHONE,
        OPSTR_READ_SMS,
        OPSTR_WRITE_SMS,
        OPSTR_RECEIVE_SMS,
        OPSTR_RECEIVE_EMERGECY_SMS,
        OPSTR_RECEIVE_MMS,
        OPSTR_RECEIVE_WAP_PUSH,
        OPSTR_SEND_SMS,
        OPSTR_READ_ICC_SMS,
        OPSTR_WRITE_ICC_SMS,
        OPSTR_WRITE_SETTINGS,
        OPSTR_SYSTEM_ALERT_WINDOW,
        OPSTR_ACCESS_NOTIFICATIONS,
        OPSTR_CAMERA,
        OPSTR_RECORD_AUDIO,
        OPSTR_PLAY_AUDIO,
        OPSTR_READ_CLIPBOARD,
        OPSTR_WRITE_CLIPBOARD,
        OPSTR_TAKE_MEDIA_BUTTONS,
        OPSTR_TAKE_AUDIO_FOCUS,
        OPSTR_AUDIO_MASTER_VOLUME,
        OPSTR_AUDIO_VOICE_VOLUME,
        OPSTR_AUDIO_RING_VOLUME,
        OPSTR_AUDIO_MEDIA_VOLUME,
        OPSTR_AUDIO_ALARM_VOLUME,
        OPSTR_AUDIO_NOTIFICATION_VOLUME,
        OPSTR_AUDIO_BLUETOOTH_VOLUME,
        OPSTR_WAKE_LOCK,
        OPSTR_MONITOR_LOCATION,
        OPSTR_MONITOR_HIGH_POWER_LOCATION,
        OPSTR_GET_USAGE_STATS,
        OPSTR_MUTE_MICROPHONE,
        OPSTR_TOAST_WINDOW,
        OPSTR_PROJECT_MEDIA,
        OPSTR_ACTIVATE_VPN,
    };

    /**
     * This provides a simple name for each operation to be used
     * in debug output.
@@ -683,6 +824,60 @@ public class AppOpsManager {
            AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
    };

    /**
     * This specifies if operation is in strict mode.
     */
    private final static boolean[] sOpStrictMode = new boolean[] {
        true,     // OP_COARSE_LOCATION
        true,     // OP_FINE_LOCATION
        true,     // OP_GPS
        false,    // OP_VIBRATE
        true,     // OP_READ_CONTACTS
        true,     // OP_WRITE_CONTACTS
        true,     // OP_READ_CALL_LOG
        true,     // OP_WRITE_CALL_LOG
        false,    // OP_READ_CALENDAR
        false,    // OP_WRITE_CALENDAR
        true,     // OP_WIFI_SCAN
        false,    // OP_POST_NOTIFICATION
        false,    // OP_NEIGHBORING_CELLS
        true,     // OP_CALL_PHONE
        true,     // OP_READ_SMS
        true,     // OP_WRITE_SMS
        false,    // OP_RECEIVE_SMS
        false,    // OP_RECEIVE_EMERGECY_SMS
        true,     // OP_RECEIVE_MMS
        false,    // OP_RECEIVE_WAP_PUSH
        true,     // OP_SEND_SMS
        false,    // OP_READ_ICC_SMS
        false,    // OP_WRITE_ICC_SMS
        false,    // OP_WRITE_SETTINGS
        false,    // OP_SYSTEM_ALERT_WINDOW
        false,    // OP_ACCESS_NOTIFICATIONS
        true,     // OP_CAMERA
        true,     // OP_RECORD_AUDIO
        false,    // OP_PLAY_AUDIO
        false,    // OP_READ_CLIPBOARD
        false,    // OP_WRITE_CLIPBOARD
        false,    // OP_TAKE_MEDIA_BUTTONS
        false,    // OP_TAKE_AUDIO_FOCUS
        false,    // OP_AUDIO_MASTER_VOLUME
        false,    // OP_AUDIO_VOICE_VOLUME
        false,    // OP_AUDIO_RING_VOLUME
        false,    // OP_AUDIO_MEDIA_VOLUME
        false,    // OP_AUDIO_ALARM_VOLUME
        false,    // OP_AUDIO_NOTIFICATION_VOLUME
        false,    // OP_AUDIO_BLUETOOTH_VOLUME
        false,    // OP_WAKE_LOCK
        false,    // OP_MONITOR_LOCATION
        true,     // OP_MONITOR_HIGH_POWER_LOCATION
        false,    // OP_GET_USAGE_STATS
        false,    // OP_MUTE_MICROPHONE
        false,    // OP_TOAST_WINDOW
        false,    // OP_PROJECT_MEDIA
        false,    // OP_ACTIVATE_VPN
    };

    /**
     * This specifies whether each option is allowed to be reset
     * when resetting all app preferences.  Disable reset for
@@ -742,6 +937,7 @@ public class AppOpsManager {
    };

    private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
    private static HashMap<String, Integer> sOpStringToOp = new HashMap<String, Integer>();

    static {
        if (sOpToSwitch.length != _NUM_OP) {
@@ -752,6 +948,10 @@ public class AppOpsManager {
            throw new IllegalStateException("sOpToString length " + sOpToString.length
                    + " should be " + _NUM_OP);
        }
        if (sOpToOpString.length != _NUM_OP) {
            throw new IllegalStateException("sOpToOpString length " + sOpToOpString.length
                    + " should be " + _NUM_OP);
        }
        if (sOpNames.length != _NUM_OP) {
            throw new IllegalStateException("sOpNames length " + sOpNames.length
                    + " should be " + _NUM_OP);
@@ -780,10 +980,17 @@ public class AppOpsManager {
            throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length "
                    + sOpRestrictions.length + " should be " + _NUM_OP);
        }
        if (sOpStrictMode.length != _NUM_OP) {
            throw new IllegalStateException("sOpStrictMode length "
                    + sOpStrictMode.length + " should be " + _NUM_OP);
        }
        for (int i=0; i<_NUM_OP; i++) {
            if (sOpToString[i] != null) {
                sOpStrToOp.put(sOpToString[i], i);
            }
            if (sOpToOpString[i] != null) {
                sOpStringToOp.put(sOpToOpString[i], i);
            }
        }
    }

@@ -1456,4 +1663,44 @@ public class AppOpsManager {
    public static boolean isStrictEnable() {
        return SystemProperties.getBoolean("persist.sys.strict_op_enable", false);
    }

    /**
     * Check if op in strict mode
     * @hide
     */
    public static boolean isStrictOp(int code) {
        return sOpStrictMode[code];
    }


    /** @hide */
    public static int stringToMode(String permission) {
        if ("allowed".equalsIgnoreCase(permission)) {
            return AppOpsManager.MODE_ALLOWED;
        } else if ("ignored".equalsIgnoreCase(permission)) {
            return AppOpsManager.MODE_IGNORED;
        } else if ("ask".equalsIgnoreCase(permission)) {
            return AppOpsManager.MODE_ASK;
        }
        return AppOpsManager.MODE_ERRORED;
    }

    /** @hide */
    public static int stringOpToOp (String op) {
        Integer val = sOpStringToOp.get(op);
        if (val == null) {
            val = OP_NONE;
        }
        return val;
    }

    /** @hide */
    public boolean isControlAllowed(int op, String packageName) {
        boolean isShow = true;
        try {
            isShow = mService.isControlAllowed(op, packageName);
        } catch (RemoteException e) {
        }
        return isShow;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -42,5 +42,5 @@ interface IAppOpsService {

    void setUserRestrictions(in Bundle restrictions, int userHandle);
    void removeUser(int userHandle);

    boolean isControlAllowed(int code, String packageName);
}
+441 −0

File added.

Preview size limit exceeded, changes collapsed.

+46 −6
Original line number Diff line number Diff line
@@ -79,11 +79,15 @@ public class AppOpsService extends IAppOpsService.Stub {
    // Write at most every 30 minutes.
    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;

    // Location of policy file.
    static final String DEFAULT_POLICY_FILE = "/system/etc/appops_policy.xml";

    Context mContext;
    final AtomicFile mFile;
    final Handler mHandler;
    final Looper mLooper;
    final boolean mStrictEnable;
    AppOpsPolicy mPolicy;

    boolean mWriteScheduled;
    final Runnable mWriteRunner = new Runnable() {
@@ -223,6 +227,7 @@ public class AppOpsService extends IAppOpsService.Stub {

    public void publish(Context context) {
        mContext = context;
        readPolicy();
        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
    }

@@ -411,7 +416,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                        }
                        repCbs.addAll(cbs);
                    }
                    if (mode == this.getDefaultMode(code, uid, packageName)) {
                    if (mode == getDefaultMode(code, uid, packageName)) {
                        // If going into the default mode, prune this op
                        // if there is nothing else interesting in it.
                        pruneOp(op, uid, packageName);
@@ -1077,11 +1082,19 @@ public class AppOpsService extends IAppOpsService.Stub {
            if (tagName.equals("op")) {
                int code = Integer
                        .parseInt(parser.getAttributeValue(null, "n"));
                int defaultMode = getDefaultMode(code, uid, pkgName);
                Op op = new Op(uid, pkgName, code, defaultMode);
                Op op = new Op(uid, pkgName, code, AppOpsManager.MODE_ERRORED);
                String mode = parser.getAttributeValue(null, "m");
                if (mode != null) {
                    op.mode = Integer.parseInt(mode);
                } else {
                    String sDefualtMode = parser.getAttributeValue(null, "dm");
                    int defaultMode;
                    if (sDefualtMode != null) {
                        defaultMode = Integer.parseInt(sDefualtMode);
                    } else {
                        defaultMode = getDefaultMode(code, uid, pkgName);
                    }
                    op.mode = defaultMode;
                }
                String time = parser.getAttributeValue(null, "t");
                if (time != null) {
@@ -1161,9 +1174,12 @@ public class AppOpsService extends IAppOpsService.Stub {
                            AppOpsManager.OpEntry op = ops.get(j);
                            out.startTag(null, "op");
                            out.attribute(null, "n", Integer.toString(op.getOp()));
                            if (op.getMode() != this.getDefaultMode(op.getOp(),
                                    pkg.getUid(), pkg.getPackageName())) {
                            int defaultMode = getDefaultMode(op.getOp(),
                                    pkg.getUid(), pkg.getPackageName());
                            if (op.getMode() != defaultMode) {
                                out.attribute(null, "m", Integer.toString(op.getMode()));
                            } else {
                                out.attribute(null, "dm", Integer.toString(defaultMode));
                            }
                            long time = op.getTime();
                            if (time != 0) {
@@ -1398,8 +1414,15 @@ public class AppOpsService extends IAppOpsService.Stub {
    }

    private int getDefaultMode(int code, int uid, String packageName) {
        return AppOpsManager.opToDefaultMode(code,
        int mode = AppOpsManager.opToDefaultMode(code,
                isStrict(code, uid, packageName));
        if (AppOpsManager.isStrictOp(code) && mPolicy != null) {
            int policyMode = mPolicy.getDefualtMode(code, packageName);
            if (policyMode != AppOpsManager.MODE_ERRORED) {
                mode = policyMode;
            }
        }
        return mode;
    }

    private boolean isStrict(int code, int uid, String packageName) {
@@ -1514,4 +1537,21 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    private void readPolicy() {
        if (mStrictEnable) {
            mPolicy = new AppOpsPolicy(new File(DEFAULT_POLICY_FILE), mContext);
            mPolicy.readPolicy();
            mPolicy.debugPoilcy();
        } else {
            mPolicy = null;
        }
    }

    public boolean isControlAllowed(int code, String packageName) {
        boolean isShow = true;
        if (mPolicy != null) {
            isShow = mPolicy.isControlAllowed(code, packageName);
        }
        return isShow;
    }
}