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

Commit ee2ee0f9 authored by Billy Lau's avatar Billy Lau Committed by Android Git Automerger
Browse files

am be6bfb4c: am 83749ac9: am a6706627: Merge "Bug: 21589105 Rescope...

am be6bfb4c: am 83749ac9: am a6706627: Merge "Bug: 21589105 Rescope WRITE_SETTINGS permission (framework services perm check changes)" into mnc-dev

* commit 'be6bfb4c':
  Bug: 21589105 Rescope WRITE_SETTINGS permission (framework services perm check changes)
parents 2864e9d4 be6bfb4c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -26404,6 +26404,7 @@ package android.provider {
  public final class Settings {
  public final class Settings {
    ctor public Settings();
    ctor public Settings();
    method public static boolean canDrawOverlays(android.content.Context);
    field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
    field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
    field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
    field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
    field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
    field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
@@ -26623,6 +26624,7 @@ package android.provider {
  public static final class Settings.System extends android.provider.Settings.NameValueTable {
  public static final class Settings.System extends android.provider.Settings.NameValueTable {
    ctor public Settings.System();
    ctor public Settings.System();
    method public static boolean canWrite(android.content.Context);
    method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration);
    method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration);
    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+2 −0
Original line number Original line Diff line number Diff line
@@ -28463,6 +28463,7 @@ package android.provider {
  public final class Settings {
  public final class Settings {
    ctor public Settings();
    ctor public Settings();
    method public static boolean canDrawOverlays(android.content.Context);
    field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
    field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
    field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
    field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
    field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
    field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
@@ -28683,6 +28684,7 @@ package android.provider {
  public static final class Settings.System extends android.provider.Settings.NameValueTable {
  public static final class Settings.System extends android.provider.Settings.NameValueTable {
    ctor public Settings.System();
    ctor public Settings.System();
    method public static boolean canWrite(android.content.Context);
    method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration);
    method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration);
    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+1 −1
Original line number Original line Diff line number Diff line
@@ -778,7 +778,7 @@ public class AppOpsManager {
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS
            AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW
            AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
+162 −6
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.Application;
import android.app.Application;
import android.app.SearchManager;
import android.app.SearchManager;
import android.app.WallpaperManager;
import android.app.WallpaperManager;
@@ -41,6 +42,7 @@ import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.DropBoxManager;
import android.os.IBinder;
import android.os.IBinder;
@@ -564,13 +566,14 @@ public final class Settings {
            "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
            "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";


    /**
    /**
     * Activity Action: Show settings to toggle permission to draw on top of
     * Activity Action: Show screen for controlling which apps can draw on top of other apps.
     * other apps.
     * <p>
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * safeguard against this.
     * <p>
     * <p>
     * Input: Nothing.
     * Input: Optionally, the Intent's data URI can specify the application package name to
     * directly invoke the management GUI specific to the package name. For example
     * "package:com.my.app".
     * <p>
     * <p>
     * Output: Nothing.
     * Output: Nothing.
     */
     */
@@ -579,13 +582,15 @@ public final class Settings {
            "android.settings.action.MANAGE_OVERLAY_PERMISSION";
            "android.settings.action.MANAGE_OVERLAY_PERMISSION";


    /**
    /**
     * Activity Action: Show settings to toggle apps' capablity to
     * Activity Action: Show screen for controlling which apps are allowed to write/modify
     * to read/write system settings.
     * system settings.
     * <p>
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * safeguard against this.
     * <p>
     * <p>
     * Input: Nothing.
     * Input: Optionally, the Intent's data URI can specify the application package name to
     * directly invoke the management GUI specific to the package name. For example
     * "package:com.my.app".
     * <p>
     * <p>
     * Output: Nothing.
     * Output: Nothing.
     */
     */
@@ -1385,6 +1390,23 @@ public final class Settings {
        }
        }
    }
    }


    /**
     * An app can use this method to check if it is currently allowed to draw on top of other
     * apps. In order to be allowed to do so, an app must first declare the
     * {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission in its manifest. If it
     * is currently disallowed, it can prompt the user to grant it this capability through a
     * management UI by sending an Intent with action
     * {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}.
     *
     * @param context A context
     * @return true if the calling app can draw on top of other apps, false otherwise.
     */
    public static boolean canDrawOverlays(Context context) {
        int uid = Binder.getCallingUid();
        return Settings.isCallingPackageAllowedToDrawOverlays(context, uid, Settings
                .getPackageNameForUid(context, uid), false);
    }

    /**
    /**
     * System settings, containing miscellaneous system preferences.  This
     * System settings, containing miscellaneous system preferences.  This
     * table holds simple name/value pairs.  There are convenience
     * table holds simple name/value pairs.  There are convenience
@@ -3658,6 +3680,23 @@ public final class Settings {
        @Deprecated
        @Deprecated
        public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS =
        public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS =
            Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS;
            Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS;

        /**
         * An app can use this method to check if it is currently allowed to write or modify system
         * settings. In order to gain write access to the system settings, an app must declare the
         * {@link android.Manifest.permission#WRITE_SETTINGS} permission in its manifest. If it is
         * currently disallowed, it can prompt the user to grant it this capability through a
         * management UI by sending an Intent with action
         * {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}.
         *
         * @param context A context
         * @return true if the calling app can write to system settings, false otherwise
         */
        public static boolean canWrite(Context context) {
            int uid = Binder.getCallingUid();
            return isCallingPackageAllowedToWriteSettings(context, uid, getPackageNameForUid(
                    context, uid), false);
        }
    }
    }


    /**
    /**
@@ -8205,4 +8244,121 @@ public final class Settings {
    public static String getGTalkDeviceId(long androidId) {
    public static String getGTalkDeviceId(long androidId) {
        return "android-" + Long.toHexString(androidId);
        return "android-" + Long.toHexString(androidId);
    }
    }

    /**
     * Performs a strict and comprehensive check of whether a calling package is allowed to
     * write/modify system settings, as the condition differs for pre-M, M+, and
     * privileged/preinstalled apps. If the provided uid does not match the
     * callingPackage, a negative result will be returned.
     * @hide
     */
    public static boolean isCallingPackageAllowedToWriteSettings(Context context, int uid,
            String callingPackage, boolean throwException) {
        return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
                callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS,
                android.Manifest.permission.WRITE_SETTINGS, false);
    }

    /**
     * Performs a strict and comprehensive check of whether a calling package is allowed to
     * write/modify system settings, as the condition differs for pre-M, M+, and
     * privileged/preinstalled apps. If the provided uid does not match the
     * callingPackage, a negative result will be returned.
     *
     * Note: if the check is successful, the operation of this app will be updated to the
     * current time.
     * @hide
     */
    public static boolean checkAndNoteWriteSettingsOperation(Context context, int uid,
            String callingPackage, boolean throwException) {
        return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
                callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS,
                android.Manifest.permission.WRITE_SETTINGS, true);
    }

    /**
     * Performs a strict and comprehensive check of whether a calling package is allowed to
     * draw on top of other apps, as the conditions differs for pre-M, M+, and
     * privileged/preinstalled apps. If the provided uid does not match the callingPackage,
     * a negative result will be returned.
     * @hide
     */
    public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid,
            String callingPackage, boolean throwException) {
        return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
                callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
                android.Manifest.permission.SYSTEM_ALERT_WINDOW, false);
    }

    /**
     * Performs a strict and comprehensive check of whether a calling package is allowed to
     * draw on top of other apps, as the conditions differs for pre-M, M+, and
     * privileged/preinstalled apps. If the provided uid does not match the callingPackage,
     * a negative result will be returned.
     *
     * Note: if the check is successful, the operation of this app will be updated to the
     * current time.
     * @hide
     */
    public static boolean checkAndNoteDrawOverlaysOperation(Context context, int uid, String
            callingPackage, boolean throwException) {
        return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
                callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
                android.Manifest.permission.SYSTEM_ALERT_WINDOW, true);
    }

    /**
     * Helper method to perform a general and comprehensive check of whether an operation that is
     * protected by appops can be performed by a caller or not. e.g. OP_SYSTEM_ALERT_WINDOW and
     * OP_WRITE_SETTINGS
     * @hide
     */
    public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context,
            int uid, String callingPackage, boolean throwException, int appOpsOpCode, String
            permissionName, boolean makeNote) {
        if (callingPackage == null) {
            return false;
        }

        AppOpsManager appOpsMgr = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
        int mode = AppOpsManager.MODE_DEFAULT;
        if (makeNote) {
            mode = appOpsMgr.noteOpNoThrow(appOpsOpCode, uid, callingPackage);
        } else {
            mode = appOpsMgr.checkOpNoThrow(appOpsOpCode, uid, callingPackage);
        }

        switch (mode) {
            case AppOpsManager.MODE_ALLOWED:
                return true;
            case AppOpsManager.MODE_DEFAULT:
                // this is the default operating mode after an app's installation
                if (!throwException) {
                    return context.checkCallingOrSelfPermission(permissionName) ==
                        PackageManager.PERMISSION_GRANTED;
                }
            default:
                // this is for all other cases trickled down here...
                if (!throwException) {
                    return false;
                }
        }
        throw new SecurityException(callingPackage + " was not granted "
                + permissionName + " permission");
    }

    /**
     * Retrieves a correponding package name for a given uid. It will query all
     * packages that are associated with the given uid, but it will return only
     * the zeroth result.
     * Note: If package could not be found, a null is returned.
     * @hide
     */
    public static String getPackageNameForUid(Context context, int uid) {
        String[] packages = context.getPackageManager().getPackagesForUid(uid);
        if (packages == null) {
            return null;
        }
        return packages[0];
    }
}
}
+8 −40
Original line number Original line Diff line number Diff line
@@ -643,11 +643,6 @@ public class SettingsProvider extends ContentProvider {
        // Make sure the caller can change the settings - treated as secure.
        // Make sure the caller can change the settings - treated as secure.
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);


        // Verify whether this operation is allowed for the calling package.
        if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
            return false;
        }

        // Resolve the userId on whose behalf the call is made.
        // Resolve the userId on whose behalf the call is made.
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);


@@ -773,11 +768,6 @@ public class SettingsProvider extends ContentProvider {
        // Make sure the caller can change the settings.
        // Make sure the caller can change the settings.
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);


        // Verify whether this operation is allowed for the calling package.
        if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
            return false;
        }

        // Resolve the userId on whose behalf the call is made.
        // Resolve the userId on whose behalf the call is made.
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);


@@ -904,14 +894,13 @@ public class SettingsProvider extends ContentProvider {


    private boolean mutateSystemSetting(String name, String value, int runAsUserId,
    private boolean mutateSystemSetting(String name, String value, int runAsUserId,
            int operation) {
            int operation) {
        // Check for permissions first.
        if (!hasWriteSecureSettingsPermission()) {
        if (!hasPermissionsToMutateSystemSettings()) {
            // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this
            // operation is allowed for the calling package through appops.
            if (!Settings.checkAndNoteWriteSettingsOperation(getContext(),
                    Binder.getCallingUid(), getCallingPackage(), true)) {
                return false;
                return false;
            }
            }

        // Verify whether this operation is allowed for the calling package.
        if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
            return false;
        }
        }


        // Enforce what the calling package can mutate the system settings.
        // Enforce what the calling package can mutate the system settings.
@@ -956,25 +945,13 @@ public class SettingsProvider extends ContentProvider {
        }
        }
    }
    }


    private boolean hasPermissionsToMutateSystemSettings() {
    private boolean hasWriteSecureSettingsPermission() {
        // Write secure settings is a more protected permission. If caller has it we are good.
        // Write secure settings is a more protected permission. If caller has it we are good.
        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
                == PackageManager.PERMISSION_GRANTED) {
                == PackageManager.PERMISSION_GRANTED) {
            return true;
            return true;
        }
        }


        // The write settings permission gates mutation of system settings.
        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SETTINGS)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        }

        // Excpet we let system apps change system settings without the permission.
        PackageInfo packageInfo = getCallingPackageInfoOrThrow();
        if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            return true;
        }

        return false;
        return false;
    }
    }


@@ -1102,15 +1079,6 @@ public class SettingsProvider extends ContentProvider {
        }
        }
    }
    }


    private boolean isAppOpWriteSettingsAllowedForCallingPackage() {
        final int callingUid = Binder.getCallingUid();

        mAppOpsManager.checkPackage(Binder.getCallingUid(), getCallingPackage());

        return mAppOpsManager.noteOp(AppOpsManager.OP_WRITE_SETTINGS, callingUid,
                getCallingPackage()) == AppOpsManager.MODE_ALLOWED;
    }

    private void enforceWritePermission(String permission) {
    private void enforceWritePermission(String permission) {
        if (getContext().checkCallingOrSelfPermission(permission)
        if (getContext().checkCallingOrSelfPermission(permission)
                != PackageManager.PERMISSION_GRANTED) {
                != PackageManager.PERMISSION_GRANTED) {
Loading