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

Commit 78f4347c authored by Matt Pape's avatar Matt Pape
Browse files

Add a DeviceConfig.Properties.Builder class.

Test: atest FrameworksCoreTests:DeviceConfigTest
      atest SettingsProviderTest:DeviceConfigServiceTest
Bug: 136135417

Change-Id: I2e1b2d467ba0b0590ef216eb10d42f73ba1ccda0
parent 690ac62a
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -7110,6 +7110,16 @@ package android.provider {
    method @Nullable public String getString(@NonNull String, @Nullable String);
    method @Nullable public String getString(@NonNull String, @Nullable String);
  }
  }
  public static final class DeviceConfig.Properties.Builder {
    ctor public DeviceConfig.Properties.Builder(@NonNull String);
    method @NonNull public android.provider.DeviceConfig.Properties build();
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setBoolean(@NonNull String, boolean);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setFloat(@NonNull String, float);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setInt(@NonNull String, int);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setLong(@NonNull String, long);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setString(@NonNull String, @Nullable String);
  }
  public final class DocumentsContract {
  public final class DocumentsContract {
    method public static boolean isManageMode(@NonNull android.net.Uri);
    method public static boolean isManageMode(@NonNull android.net.Uri);
    method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
    method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
+10 −0
Original line number Original line Diff line number Diff line
@@ -2452,6 +2452,16 @@ package android.provider {
    method @Nullable public String getString(@NonNull String, @Nullable String);
    method @Nullable public String getString(@NonNull String, @Nullable String);
  }
  }


  public static final class DeviceConfig.Properties.Builder {
    ctor public DeviceConfig.Properties.Builder(@NonNull String);
    method @NonNull public android.provider.DeviceConfig.Properties build();
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setBoolean(@NonNull String, boolean);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setFloat(@NonNull String, float);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setInt(@NonNull String, int);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setLong(@NonNull String, long);
    method @NonNull public android.provider.DeviceConfig.Properties.Builder setString(@NonNull String, @Nullable String);
  }

  public final class MediaStore {
  public final class MediaStore {
    method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
+96 −4
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;


import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
@@ -734,19 +735,19 @@ public final class DeviceConfig {
        List<String> pathSegments = uri.getPathSegments();
        List<String> pathSegments = uri.getPathSegments();
        // pathSegments(0) is "config"
        // pathSegments(0) is "config"
        final String namespace = pathSegments.get(1);
        final String namespace = pathSegments.get(1);
        Map<String, String> propertyMap = new ArrayMap<>();
        Properties.Builder propBuilder = new Properties.Builder(namespace);
        try {
        try {
            Properties allProperties = getProperties(namespace);
            Properties allProperties = getProperties(namespace);
            for (int i = 2; i < pathSegments.size(); ++i) {
            for (int i = 2; i < pathSegments.size(); ++i) {
                String key = pathSegments.get(i);
                String key = pathSegments.get(i);
                propertyMap.put(key, allProperties.getString(key, null));
                propBuilder.setString(key, allProperties.getString(key, null));
            }
            }
        } catch (SecurityException e) {
        } catch (SecurityException e) {
            // Silently failing to not crash binder or listener threads.
            // Silently failing to not crash binder or listener threads.
            Log.e(TAG, "OnPropertyChangedListener update failed: permission violation.");
            Log.e(TAG, "OnPropertyChangedListener update failed: permission violation.");
            return;
            return;
        }
        }
        Properties properties = new Properties(namespace, propertyMap);
        Properties properties = propBuilder.build();


        synchronized (sLock) {
        synchronized (sLock) {
            for (int i = 0; i < sListeners.size(); i++) {
            for (int i = 0; i < sListeners.size(); i++) {
@@ -819,6 +820,7 @@ public final class DeviceConfig {
    public static class Properties {
    public static class Properties {
        private final String mNamespace;
        private final String mNamespace;
        private final HashMap<String, String> mMap;
        private final HashMap<String, String> mMap;
        private Set<String> mKeyset;


        /**
        /**
         * Create a mapping of properties to values and the namespace they belong to.
         * Create a mapping of properties to values and the namespace they belong to.
@@ -849,7 +851,10 @@ public final class DeviceConfig {
         */
         */
        @NonNull
        @NonNull
        public Set<String> getKeyset() {
        public Set<String> getKeyset() {
            return mMap.keySet();
            if (mKeyset == null) {
                mKeyset = Collections.unmodifiableSet(mMap.keySet());
            }
            return mKeyset;
        }
        }


        /**
        /**
@@ -944,6 +949,93 @@ public final class DeviceConfig {
                return defaultValue;
                return defaultValue;
            }
            }
        }
        }

        /**
         * Builder class for the construction of {@link Properties} objects.
         */
        public static final class Builder {
            @NonNull
            private final String mNamespace;
            @NonNull
            private final Map<String, String> mKeyValues = new HashMap<>();

            /**
             * Create a new Builders for the specified namespace.
             * @param namespace non null namespace.
             */
            public Builder(@NonNull String namespace) {
                mNamespace = namespace;
            }

            /**
             * Add a new property with the specified key and value.
             * @param name non null name of the property.
             * @param value nullable string value of the property.
             * @return this Builder object
             */
            @NonNull
            public Builder setString(@NonNull String name, @Nullable String value) {
                mKeyValues.put(name, value);
                return this;
            }

            /**
             * Add a new property with the specified key and value.
             * @param name non null name of the property.
             * @param value nullable string value of the property.
             * @return this Builder object
             */
            @NonNull
            public Builder setBoolean(@NonNull String name, boolean value) {
                mKeyValues.put(name, Boolean.toString(value));
                return this;
            }

            /**
             * Add a new property with the specified key and value.
             * @param name non null name of the property.
             * @param value int value of the property.
             * @return this Builder object
             */
            @NonNull
            public Builder setInt(@NonNull String name, int value) {
                mKeyValues.put(name, Integer.toString(value));
                return this;
            }

            /**
             * Add a new property with the specified key and value.
             * @param name non null name of the property.
             * @param value long value of the property.
             * @return this Builder object
             */
            @NonNull
            public Builder setLong(@NonNull String name, long value) {
                mKeyValues.put(name, Long.toString(value));
                return this;
            }

            /**
             * Add a new property with the specified key and value.
             * @param name non null name of the property.
             * @param value float value of the property.
             * @return this Builder object
             */
            @NonNull
            public Builder setFloat(@NonNull String name, float value) {
                mKeyValues.put(name, Float.toString(value));
                return this;
            }

            /**
             * Create a new {@link Properties} object.
             * @return non null Properties.
             */
            @NonNull
            public Properties build() {
                return new Properties(mNamespace, mKeyValues);
            }
        }
    }
    }


}
}
+34 −22
Original line number Original line Diff line number Diff line
@@ -33,9 +33,6 @@ import org.junit.Assert;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;


import java.util.HashMap;
import java.util.Map;

/** Tests that ensure appropriate settings are backed up. */
/** Tests that ensure appropriate settings are backed up. */
@Presubmit
@Presubmit
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
@@ -489,21 +486,19 @@ public class DeviceConfigTest {


    @Test
    @Test
    public void setProperties() throws DeviceConfig.BadConfigException {
    public void setProperties() throws DeviceConfig.BadConfigException {
        Map<String, String> keyValues = new HashMap<>();
        Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
        keyValues.put(KEY, VALUE);
                .setString(KEY2, VALUE2).build();
        keyValues.put(KEY2, VALUE2);


        DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
        DeviceConfig.setProperties(properties);
        Properties properties = DeviceConfig.getProperties(NAMESPACE);
        properties = DeviceConfig.getProperties(NAMESPACE);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);


        Map<String, String> newKeyValues = new HashMap<>();
        properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE2)
        newKeyValues.put(KEY, VALUE2);
                .setString(KEY3, VALUE3).build();
        newKeyValues.put(KEY3, VALUE3);


        DeviceConfig.setProperties(new Properties(NAMESPACE, newKeyValues));
        DeviceConfig.setProperties(properties);
        properties = DeviceConfig.getProperties(NAMESPACE);
        properties = DeviceConfig.getProperties(NAMESPACE);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY3);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY3);
        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2);
        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2);
@@ -515,17 +510,14 @@ public class DeviceConfigTest {


    @Test
    @Test
    public void setProperties_multipleNamespaces() throws DeviceConfig.BadConfigException {
    public void setProperties_multipleNamespaces() throws DeviceConfig.BadConfigException {
        Map<String, String> keyValues = new HashMap<>();
        keyValues.put(KEY, VALUE);
        keyValues.put(KEY2, VALUE2);

        Map<String, String> keyValues2 = new HashMap<>();
        keyValues2.put(KEY2, VALUE);
        keyValues2.put(KEY3, VALUE2);

        final String namespace2 = "namespace2";
        final String namespace2 = "namespace2";
        DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
        Properties properties1 = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
        DeviceConfig.setProperties(new Properties(namespace2, keyValues2));
                .setString(KEY2, VALUE2).build();
        Properties properties2 = new Properties.Builder(namespace2).setString(KEY2, VALUE)
                .setString(KEY3, VALUE2).build();

        DeviceConfig.setProperties(properties1);
        DeviceConfig.setProperties(properties2);


        Properties properties = DeviceConfig.getProperties(NAMESPACE);
        Properties properties = DeviceConfig.getProperties(NAMESPACE);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
@@ -549,6 +541,26 @@ public class DeviceConfigTest {
        deleteViaContentProvider(namespace2, KEY3);
        deleteViaContentProvider(namespace2, KEY3);
    }
    }


    @Test
    public void propertiesBuilder() {
        boolean booleanValue = true;
        int intValue = 123;
        float floatValue = 4.56f;
        long longValue = -789L;
        String key4 = "key4";
        String key5 = "key5";

        Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
                .setBoolean(KEY2, booleanValue).setInt(KEY3, intValue).setLong(key4, longValue)
                .setFloat(key5, floatValue).build();
        assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
        assertThat(properties.getString(KEY, "defaultValue")).isEqualTo(VALUE);
        assertThat(properties.getBoolean(KEY2, false)).isEqualTo(booleanValue);
        assertThat(properties.getInt(KEY3, 0)).isEqualTo(intValue);
        assertThat(properties.getLong("key4", 0L)).isEqualTo(longValue);
        assertThat(properties.getFloat("key5", 0f)).isEqualTo(floatValue);
    }

    // TODO(mpape): resolve b/142727848 and re-enable listener tests
    // TODO(mpape): resolve b/142727848 and re-enable listener tests
//    @Test
//    @Test
//    public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
//    public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
+9 −4
Original line number Original line Diff line number Diff line
@@ -69,8 +69,11 @@ public class DeviceConfigProxyFake extends DeviceConfigProxy {
        }
        }


        for (Pair<Executor, OnPropertiesChangedListener> listener : mListeners) {
        for (Pair<Executor, OnPropertiesChangedListener> listener : mListeners) {
            listener.first.execute(() -> listener.second.onPropertiesChanged(
            Properties.Builder propBuilder = new Properties.Builder(namespace);
                    new Properties(namespace, mProperties.get(namespace))));
            for (String key : mProperties.get(namespace).keySet()) {
                propBuilder.setString(key, mProperties.get(namespace).get(key));
            }
            listener.first.execute(() -> listener.second.onPropertiesChanged(propBuilder.build()));
        }
        }
        return true;
        return true;
    }
    }
@@ -88,10 +91,12 @@ public class DeviceConfigProxyFake extends DeviceConfigProxy {


    private Properties propsForNamespaceAndName(String namespace, String name) {
    private Properties propsForNamespaceAndName(String namespace, String name) {
        if (mProperties.containsKey(namespace) && mProperties.get(namespace).containsKey(name)) {
        if (mProperties.containsKey(namespace) && mProperties.get(namespace).containsKey(name)) {
            return new Properties(namespace, mProperties.get(namespace));
            return new Properties.Builder(namespace)
                    .setString(name, mProperties.get(namespace).get(name)).build();
        }
        }
        if (mDefaultProperties.containsKey(namespace)) {
        if (mDefaultProperties.containsKey(namespace)) {
            return new Properties(namespace, mDefaultProperties.get(namespace));
            return new Properties.Builder(namespace)
                    .setString(name, mDefaultProperties.get(namespace).get(name)).build();
        }
        }


        return null;
        return null;