Merge changes from topic "DeviceConfigInterface"
* changes: Remove DeviceConfigInterface from Services & refactor FakeDeviceConfigInterface to use android.provider.DeviceConfigInterface Add DeviceConfigInterface.java Re-enable DeviceConfig onPropertiesChangedListener tests.
This commit is contained in:
committed by
Android (Google) Code Review
commit
b6e915f50b
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,57 +14,103 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.utils;
|
||||
package android.provider;
|
||||
|
||||
import static android.provider.Settings.ResetMode;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.DeviceConfig.BadConfigException;
|
||||
import android.provider.DeviceConfig.Properties;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Abstraction around {@link DeviceConfig} to allow faking device configuration in tests.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface DeviceConfigInterface {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getProperty
|
||||
*/
|
||||
@Nullable
|
||||
String getProperty(@NonNull String namespace, @NonNull String name);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getProperties
|
||||
*/
|
||||
@NonNull
|
||||
Properties getProperties(@NonNull String namespace, @NonNull String... names);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#setProperty
|
||||
*/
|
||||
boolean setProperty(@NonNull String namespace, @NonNull String name, @Nullable String value,
|
||||
boolean makeDefault);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#setProperties
|
||||
*/
|
||||
boolean setProperties(@NonNull Properties properties) throws BadConfigException;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#deleteProperty
|
||||
*/
|
||||
boolean deleteProperty(@NonNull String namespace, @NonNull String name);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#resetToDefaults
|
||||
*/
|
||||
void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getString
|
||||
*/
|
||||
@NonNull
|
||||
String getString(@NonNull String namespace, @NonNull String name, @NonNull String defaultValue);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getInt
|
||||
*/
|
||||
int getInt(@NonNull String namespace, @NonNull String name, int defaultValue);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getLong
|
||||
*/
|
||||
long getLong(@NonNull String namespace, @NonNull String name, long defaultValue);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getBoolean
|
||||
*/
|
||||
boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#getFloat
|
||||
*/
|
||||
float getFloat(@NonNull String namespace, @NonNull String name, float defaultValue);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#addOnPropertiesChangedListener
|
||||
*/
|
||||
void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
|
||||
@NonNull DeviceConfig.OnPropertiesChangedListener listener);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @see DeviceConfig#removeOnPropertiesChangedListener
|
||||
*/
|
||||
void removeOnPropertiesChangedListener(
|
||||
@@ -72,13 +118,46 @@ public interface DeviceConfigInterface {
|
||||
|
||||
/**
|
||||
* Calls through to the real {@link DeviceConfig}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
DeviceConfigInterface REAL = new DeviceConfigInterface() {
|
||||
@Override
|
||||
public String getProperty(String namespace, String name) {
|
||||
return DeviceConfig.getProperty(namespace, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceConfig.Properties getProperties(@NonNull String namespace,
|
||||
@NonNull String... names) {
|
||||
return DeviceConfig.getProperties(namespace, names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperty(@NonNull String namespace,
|
||||
@NonNull String name,
|
||||
@Nullable String value, boolean makeDefault) {
|
||||
return DeviceConfig.setProperty(namespace, name, value, makeDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperties(@NonNull Properties properties)
|
||||
throws BadConfigException {
|
||||
return DeviceConfig.setProperties(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteProperty(@NonNull String namespace,
|
||||
@NonNull String name) {
|
||||
return DeviceConfig.deleteProperty(namespace, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetToDefaults(int resetMode, @Nullable String namespace) {
|
||||
DeviceConfig.resetToDefaults(resetMode, namespace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String namespace, String name, String defaultValue) {
|
||||
return DeviceConfig.getString(namespace, name, defaultValue);
|
||||
@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Bundle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -35,6 +36,12 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Tests that ensure appropriate settings are backed up. */
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -701,66 +708,67 @@ public class DeviceConfigTest {
|
||||
assertThat(result.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
// TODO(mpape): resolve b/142727848 and re-enable listener tests
|
||||
// @Test
|
||||
// public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
|
||||
// final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
//
|
||||
// DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
|
||||
// assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
|
||||
// assertThat(properties.getKeyset()).contains(KEY);
|
||||
// assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
|
||||
// countDownLatch.countDown();
|
||||
// };
|
||||
//
|
||||
// try {
|
||||
// DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
|
||||
// ActivityThread.currentApplication().getMainExecutor(), changeListener);
|
||||
// DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
|
||||
// assertThat(countDownLatch.await(
|
||||
// WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
|
||||
// } catch (InterruptedException e) {
|
||||
// Assert.fail(e.getMessage());
|
||||
// } finally {
|
||||
// DeviceConfig.removeOnPropertiesChangedListener(changeListener);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void onPropertiesChangedListener_setPropertiesCallback() throws InterruptedException {
|
||||
// final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
// DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
|
||||
// DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
|
||||
//
|
||||
// Map<String, String> keyValues = new HashMap<>(2);
|
||||
// keyValues.put(KEY, VALUE2);
|
||||
// keyValues.put(KEY3, VALUE3);
|
||||
// Properties setProperties = new Properties(NAMESPACE, keyValues);
|
||||
//
|
||||
// DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
|
||||
// assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
|
||||
// assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
|
||||
// // KEY updated from VALUE to VALUE2
|
||||
// assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2);
|
||||
// // KEY2 deleted (returns default_value)
|
||||
// assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value");
|
||||
// //KEY3 added with VALUE3
|
||||
// assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3);
|
||||
// countDownLatch.countDown();
|
||||
// };
|
||||
//
|
||||
// try {
|
||||
// DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
|
||||
// ActivityThread.currentApplication().getMainExecutor(), changeListener);
|
||||
// DeviceConfig.setProperties(setProperties);
|
||||
// assertThat(countDownLatch.await(
|
||||
// WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
|
||||
// } catch (InterruptedException e) {
|
||||
// Assert.fail(e.getMessage());
|
||||
// } finally {
|
||||
// DeviceConfig.removeOnPropertiesChangedListener(changeListener);
|
||||
// }
|
||||
// }
|
||||
@Test
|
||||
public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
|
||||
assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
|
||||
assertThat(properties.getKeyset()).contains(KEY);
|
||||
assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
|
||||
countDownLatch.countDown();
|
||||
};
|
||||
|
||||
try {
|
||||
DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
|
||||
Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(),
|
||||
changeListener);
|
||||
DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
|
||||
assertThat(countDownLatch.await(
|
||||
WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
} finally {
|
||||
DeviceConfig.removeOnPropertiesChangedListener(changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPropertiesChangedListener_setPropertiesCallback() {
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
|
||||
DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
|
||||
|
||||
Map<String, String> keyValues = new HashMap<>(2);
|
||||
keyValues.put(KEY, VALUE2);
|
||||
keyValues.put(KEY3, VALUE3);
|
||||
Properties setProperties = new Properties(NAMESPACE, keyValues);
|
||||
|
||||
DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
|
||||
assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
|
||||
assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
|
||||
// KEY updated from VALUE to VALUE2
|
||||
assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2);
|
||||
// KEY2 deleted (returns default_value)
|
||||
assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value");
|
||||
//KEY3 added with VALUE3
|
||||
assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3);
|
||||
countDownLatch.countDown();
|
||||
};
|
||||
|
||||
try {
|
||||
DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
|
||||
Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(),
|
||||
changeListener);
|
||||
DeviceConfig.setProperties(setProperties);
|
||||
assertThat(countDownLatch.await(
|
||||
WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
|
||||
} catch (InterruptedException | DeviceConfig.BadConfigException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
} finally {
|
||||
DeviceConfig.removeOnPropertiesChangedListener(changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncDisabling() throws Exception {
|
||||
|
||||
@@ -207,10 +207,3 @@ prebuilt_etc {
|
||||
name: "protolog.conf.json.gz",
|
||||
src: ":services.core.json.gz",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "services.core-sources-deviceconfig-interface",
|
||||
srcs: [
|
||||
"java/com/android/server/utils/DeviceConfigInterface.java",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.DeviceConfigInterface;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.IndentingPrintWriter;
|
||||
@@ -61,7 +62,6 @@ import com.android.server.display.utils.AmbientFilterFactory;
|
||||
import com.android.server.sensors.SensorManagerInternal;
|
||||
import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
|
||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
@@ -22,12 +22,12 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.res.Resources;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.DeviceConfigInterface;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_
|
||||
|
||||
import android.provider.AndroidDeviceConfig;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.DeviceConfigInterface;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -206,6 +206,7 @@ import android.os.SystemService;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.DeviceConfigInterface;
|
||||
import android.provider.Settings;
|
||||
import android.service.vr.IVrManager;
|
||||
import android.service.vr.IVrStateCallbacks;
|
||||
@@ -300,7 +301,6 @@ import com.android.server.input.InputManagerService;
|
||||
import com.android.server.policy.WindowManagerPolicy;
|
||||
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
|
||||
import com.android.server.power.ShutdownThread;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
import com.android.server.utils.PriorityDump;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
|
||||
@@ -144,7 +144,6 @@ java_library {
|
||||
"utils/**/*.java",
|
||||
"utils/**/*.kt",
|
||||
"utils-mockito/**/*.kt",
|
||||
":services.core-sources-deviceconfig-interface",
|
||||
],
|
||||
static_libs: [
|
||||
"junit",
|
||||
@@ -161,7 +160,6 @@ java_library {
|
||||
"utils/**/*.java",
|
||||
"utils/**/*.kt",
|
||||
"utils-mockito/**/*.kt",
|
||||
":services.core-sources-deviceconfig-interface",
|
||||
],
|
||||
static_libs: [
|
||||
"junit",
|
||||
|
||||
@@ -18,13 +18,14 @@ package com.android.server.testutils;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.DeviceConfigInterface;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -33,10 +34,17 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FakeDeviceConfigInterface implements DeviceConfigInterface {
|
||||
|
||||
private static final String COMPOSITE_DELIMITER = "/";
|
||||
private Map<String, String> mProperties = new HashMap<>();
|
||||
private ArrayMap<DeviceConfig.OnPropertiesChangedListener, Pair<String, Executor>> mListeners =
|
||||
new ArrayMap<>();
|
||||
|
||||
private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
|
||||
Preconditions.checkNotNull(namespace);
|
||||
Preconditions.checkNotNull(name);
|
||||
return namespace + COMPOSITE_DELIMITER + name;
|
||||
}
|
||||
|
||||
public void clearProperties() {
|
||||
mProperties.clear();
|
||||
}
|
||||
@@ -90,6 +98,59 @@ public class FakeDeviceConfigInterface implements DeviceConfigInterface {
|
||||
return mProperties.get(createCompositeName(namespace, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceConfig.Properties getProperties(String namespace, String... names) {
|
||||
if (!mProperties.keySet().contains(namespace)) {
|
||||
return new DeviceConfig.Properties(namespace, null);
|
||||
}
|
||||
DeviceConfig.Properties.Builder propertiesBuilder = new DeviceConfig.Properties.Builder(
|
||||
namespace);
|
||||
|
||||
for (String compositeName : mProperties.keySet()) {
|
||||
if (compositeName.split(COMPOSITE_DELIMITER).length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String existingPropertyNamespace = compositeName.split(COMPOSITE_DELIMITER)[0];
|
||||
String existingPropertyName = compositeName.split(COMPOSITE_DELIMITER)[1];
|
||||
|
||||
if ((names.length == 0 && existingPropertyNamespace.equals(namespace)) || Arrays.asList(
|
||||
names).contains(compositeName)) {
|
||||
propertiesBuilder.setString(existingPropertyName, mProperties.get(compositeName));
|
||||
}
|
||||
}
|
||||
|
||||
return propertiesBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperty(String namespace, String name, String value, boolean makeDefault) {
|
||||
putPropertyAndNotify(namespace, name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperties(DeviceConfig.Properties properties)
|
||||
throws DeviceConfig.BadConfigException {
|
||||
for (String property : properties.getKeyset()) {
|
||||
String compositeName = createCompositeName(properties.getNamespace(), property);
|
||||
putPropertyAndNotify(properties.getNamespace(), compositeName,
|
||||
properties.getString(property, ""));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteProperty(String namespace, String name) {
|
||||
mProperties.remove(createCompositeName(namespace, name));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetToDefaults(int resetMode, String namespace) {
|
||||
clearProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String namespace, String name, String defaultValue) {
|
||||
String value = getProperty(namespace, name);
|
||||
@@ -166,10 +227,4 @@ public class FakeDeviceConfigInterface implements DeviceConfigInterface {
|
||||
DeviceConfig.OnPropertiesChangedListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
|
||||
Preconditions.checkNotNull(namespace);
|
||||
Preconditions.checkNotNull(name);
|
||||
return namespace + "/" + name;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user