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

Commit 095a4d34 authored by Bohdan Petrivskyy's avatar Bohdan Petrivskyy
Browse files

Adds scoped DeviceConfig reset support to RescueParty.

When there is a new DeviceConfig access related calling package
will be monitored for 48 hours for crashes. If crashes occur,
only relevant accessed namespaces are reset.

Test: atest RescuePartyTest.

Bug: 136134408

Change-Id: I8d585496783812842c34f440e250469c2d510f3a
parent c6583833
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ package android {
    field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
    field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE";
    field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE";
    field public static final String MONITOR_DEVICE_CONFIG_ACCESS = "android.permission.MONITOR_DEVICE_CONFIG_ACCESS";
    field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
    field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
    field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
+8 −0
Original line number Diff line number Diff line
@@ -786,6 +786,14 @@ public final class DeviceConfig {
        }
    }

    /**
     * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION;
     * @hide
     */
    public static @NonNull List<String> getPublicNamespaces() {
        return PUBLIC_NAMESPACES;
    }

    /**
     * Interface for monitoring changes to properties. Implementations will receive callbacks when
     * properties change, including a {@link Properties} object which contains a single namespace
+57 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.IBinder;
import android.os.LocaleList;
import android.os.PowerManager.AutoPowerSaveModeTriggers;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -2145,6 +2146,11 @@ public final class Settings {
     */
    public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
    /**
     * @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests
     */
    public static final String CALL_METHOD_MONITOR_CALLBACK_KEY = "_monitor_callback_key";
    /**
     * @hide - String argument extra to the fast-path call()-based requests
     */
@@ -2203,6 +2209,26 @@ public final class Settings {
    /** @hide - Private call() method to reset to defaults the 'configuration' table */
    public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
    /** @hide - Private call() method to register monitor callback for 'configuration' table */
    public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
            "REGISTER_MONITOR_CALLBACK_config";
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type";
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_ACCESS_CALLBACK = "access_callback";
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_NAMESPACE_UPDATED_CALLBACK =
            "namespace_updated_callback";
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_NAMESPACE = "namespace";
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_CALLING_PACKAGE = "calling_package";
    /**
     * Activity Extra: Limit available options in launched activity based on the given authority.
     * <p>
@@ -14082,6 +14108,37 @@ public final class Settings {
            }
        }
        /**
         * Register callback for monitoring Config table.
         *
         * @param resolver Handle to the content resolver.
         * @param callback callback to register
         *
         * @hide
         */
        @SystemApi
        @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS)
        public static void registerMonitorCallback(@NonNull ContentResolver resolver,
                @NonNull RemoteCallback callback) {
            registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback);
        }
        private static void registerMonitorCallbackAsUser(
                @NonNull ContentResolver resolver, @UserIdInt int userHandle,
                @NonNull RemoteCallback callback) {
            try {
                Bundle arg = new Bundle();
                arg.putInt(CALL_METHOD_USER_KEY, userHandle);
                arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback);
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                cp.call(resolver.getPackageName(), resolver.getFeatureId(),
                        sProviderHolder.mUri.getAuthority(),
                        CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
            } catch (RemoteException e) {
                Log.w(TAG, "Can't register config monitor callback", e);
            }
        }
        private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
            Preconditions.checkNotNull(namespace);
            Preconditions.checkNotNull(name);
+5 −0
Original line number Diff line number Diff line
@@ -2695,6 +2695,11 @@
    <permission android:name="android.permission.READ_DEVICE_CONFIG"
        android:protectionLevel="signature|preinstalled" />

    <!-- @SystemApi @hide Allows an application to monitor config settings access.
    <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
        android:protectionLevel="signature"/>

    <!-- @SystemApi @TestApi Allows an application to call
        {@link android.app.ActivityManager#forceStopPackage}.
        @hide -->
+75 −10
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SELinux;
import android.os.ServiceManager;
@@ -274,6 +275,9 @@ public class SettingsProvider extends ContentProvider {

    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private RemoteCallback mConfigMonitorCallback;

    @GuardedBy("mLock")
    private SettingsRegistry mSettingsRegistry;

@@ -450,8 +454,17 @@ public class SettingsProvider extends ContentProvider {

            case Settings.CALL_METHOD_LIST_CONFIG: {
                String prefix = getSettingPrefix(args);
                return packageValuesForCallResult(getAllConfigFlags(prefix),
                Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix),
                        isTrackingGeneration(args));
                reportDeviceConfigAccess(prefix);
                return result;
            }

            case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG: {
                RemoteCallback callback = args.getParcelable(
                        Settings.CALL_METHOD_MONITOR_CALLBACK_KEY);
                setMonitorCallback(callback);
                break;
            }

            case Settings.CALL_METHOD_LIST_GLOBAL: {
@@ -1052,8 +1065,9 @@ public class SettingsProvider extends ContentProvider {
        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);

        synchronized (mLock) {
            return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM,
                    prefix, keyValues, resolveCallingPackage());
            final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
            return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
                    resolveCallingPackage());
        }
    }

@@ -2155,6 +2169,59 @@ public class SettingsProvider extends ContentProvider {
        return result;
    }

    private void setMonitorCallback(RemoteCallback callback) {
        if (callback == null) {
            return;
        }
        getContext().enforceCallingOrSelfPermission(
                Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS,
                "Permission denial: registering for config access requires: "
                        + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS);
        synchronized (mLock) {
            mConfigMonitorCallback = callback;
        }
    }

    private void reportDeviceConfigAccess(@Nullable String prefix) {
        if (prefix == null) {
            return;
        }
        String callingPackage = getCallingPackage();
        String namespace = prefix.replace("/", "");
        if (DeviceConfig.getPublicNamespaces().contains(namespace)) {
            return;
        }
        synchronized (mLock) {
            if (mConfigMonitorCallback != null) {
                Bundle callbackResult = new Bundle();
                callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE,
                        Settings.EXTRA_ACCESS_CALLBACK);
                callbackResult.putString(Settings.EXTRA_CALLING_PACKAGE, callingPackage);
                callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace);
                mConfigMonitorCallback.sendResult(callbackResult);
            }
        }
    }

    private void reportDeviceConfigUpdate(@Nullable String prefix) {
        if (prefix == null) {
            return;
        }
        String namespace = prefix.replace("/", "");
        if (DeviceConfig.getPublicNamespaces().contains(namespace)) {
            return;
        }
        synchronized (mLock) {
            if (mConfigMonitorCallback != null) {
                Bundle callbackResult = new Bundle();
                callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE,
                        Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK);
                callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace);
                mConfigMonitorCallback.sendResult(callbackResult);
            }
        }
    }

    private static int getRequestingUserId(Bundle args) {
        final int callingUserId = UserHandle.getCallingUserId();
        return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
@@ -2715,22 +2782,20 @@ public class SettingsProvider extends ContentProvider {
        }

        /**
         * Set Settings using consumed keyValues, returns true if the keyValues can be set, false
         * otherwise.
         * Set Config Settings using consumed keyValues, returns true if the keyValues can be set,
         * false otherwise.
         */
        public boolean setSettingsLocked(int type, int userId, String prefix,
        public boolean setConfigSettingsLocked(int key, String prefix,
                Map<String, String> keyValues, String packageName) {
            final int key = makeKey(type, userId);

            SettingsState settingsState = peekSettingsStateLocked(key);
            if (settingsState != null) {
                if (SETTINGS_TYPE_CONFIG == type && settingsState.isNewConfigBannedLocked(prefix,
                        keyValues)) {
                if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) {
                    return false;
                }
                List<String> changedSettings =
                        settingsState.setSettingsLocked(prefix, keyValues, packageName);
                if (!changedSettings.isEmpty()) {
                    reportDeviceConfigUpdate(prefix);
                    notifyForConfigSettingsChangeLocked(key, prefix, changedSettings);
                }
            }
Loading