summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nick Chameyev <nickchameyev@google.com> 2022-06-09 16:02:03 +0000
committer Nick Chameyev <nickchameyev@google.com> 2022-06-10 10:26:20 +0000
commit06272cf2fd9628b45f23a0b3a3cd456009f41c11 (patch)
treeafc0f586ec47d17dd6a952258a1f5fe0ee38454c
parent4316f708257d54ea27888a6d4d811514130e4ee1 (diff)
Add DeviceConfig feature flag type to SystemUI
Adds support of DeviceConfig feature flags. DeviceConfig flags are used by Phenotype A/B testing framework. Bug: 218314434 Test: change phenotype flag => check that FeatureFlags returns correct value Test: atest com.android.systemui.flags.FeatureFlagsDebugTest Test: atest com.android.systemui.flags.FeatureFlagsReleaseTest Change-Id: I7dd9e47280ba56b7f9ea552c0d44d3e36fc6b041
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt21
7 files changed, 102 insertions, 1 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index 19a53091b35c..b4646aee444c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -36,6 +36,12 @@ interface ResourceFlag<T> : Flag<T> {
val resourceId: Int
}
+interface DeviceConfigFlag<T> : Flag<T> {
+ val name: String
+ val namespace: String
+ val default: T
+}
+
interface SysPropFlag<T> : Flag<T> {
val name: String
val default: T
@@ -74,6 +80,14 @@ data class ResourceBooleanFlag @JvmOverloads constructor(
override val teamfood: Boolean = false
) : ResourceFlag<Boolean>
+data class DeviceConfigBooleanFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val name: String,
+ override val namespace: String,
+ override val default: Boolean = false,
+ override val teamfood: Boolean = false
+) : DeviceConfigFlag<Boolean>
+
data class SysPropBooleanFlag @JvmOverloads constructor(
override val id: Int,
override val name: String,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
index 9d6e3c295100..2cee2520ce55 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
@@ -29,6 +29,9 @@ interface FeatureFlags : FlagListenable {
fun isEnabled(flag: ResourceBooleanFlag): Boolean
/** Returns a boolean value for the given flag. */
+ fun isEnabled(flag: DeviceConfigBooleanFlag): Boolean
+
+ /** Returns a boolean value for the given flag. */
fun isEnabled(flag: SysPropBooleanFlag): Boolean
/** Returns a string value for the given flag. */
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index c4531b573d22..49b3908558d8 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -32,6 +32,7 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -44,6 +45,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.commandline.Command;
import com.android.systemui.statusbar.commandline.CommandRegistry;
+import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
@@ -81,6 +83,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
private final SecureSettings mSecureSettings;
private final Resources mResources;
private final SystemPropertiesHelper mSystemProperties;
+ private final DeviceConfigProxy mDeviceConfigProxy;
private final Map<Integer, Flag<?>> mAllFlags;
private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
@@ -94,6 +97,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
SystemPropertiesHelper systemProperties,
@Main Resources resources,
DumpManager dumpManager,
+ DeviceConfigProxy deviceConfigProxy,
@Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
CommandRegistry commandRegistry,
IStatusBarService barService) {
@@ -101,6 +105,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
mSecureSettings = secureSettings;
mResources = resources;
mSystemProperties = systemProperties;
+ mDeviceConfigProxy = deviceConfigProxy;
mAllFlags = allFlags;
mBarService = barService;
@@ -138,6 +143,18 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
}
@Override
+ public boolean isEnabled(@NonNull DeviceConfigBooleanFlag flag) {
+ int id = flag.getId();
+ if (!mBooleanFlagCache.containsKey(id)) {
+ boolean deviceConfigValue = mDeviceConfigProxy.getBoolean(flag.getNamespace(),
+ flag.getName(), flag.getDefault());
+ mBooleanFlagCache.put(id, readFlagValue(id, deviceConfigValue));
+ }
+
+ return mBooleanFlagCache.get(id);
+ }
+
+ @Override
public boolean isEnabled(@NonNull SysPropBooleanFlag flag) {
int id = flag.getId();
if (!mBooleanFlagCache.containsKey(id)) {
@@ -293,6 +310,8 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
} else if (flag instanceof ResourceBooleanFlag) {
setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
+ } else if (flag instanceof DeviceConfigBooleanFlag) {
+ setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
} else if (flag instanceof SysPropBooleanFlag) {
// Store SysProp flags in SystemProperties where they can read by outside parties.
mSystemProperties.setBoolean(((SysPropBooleanFlag) flag).getName(), value);
@@ -394,6 +413,10 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
return new BooleanFlag(
f.getId(), isEnabled((ResourceBooleanFlag) f), f.getTeamfood());
}
+ if (f instanceof DeviceConfigBooleanFlag) {
+ return new BooleanFlag(
+ f.getId(), isEnabled((DeviceConfigBooleanFlag) f), f.getTeamfood());
+ }
if (f instanceof SysPropBooleanFlag) {
// TODO(b/223379190): Teamfood not supported for sysprop flags yet.
return new BooleanFlag(
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
index cacef161a862..1492a2bc0ceb 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
@@ -19,6 +19,7 @@ package com.android.systemui.flags;
import static java.util.Objects.requireNonNull;
import android.content.res.Resources;
+import android.provider.DeviceConfig;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -28,6 +29,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.util.DeviceConfigProxy;
import java.io.PrintWriter;
import java.util.Map;
@@ -44,6 +46,7 @@ import javax.inject.Inject;
public class FeatureFlagsRelease implements FeatureFlags, Dumpable {
private final Resources mResources;
private final SystemPropertiesHelper mSystemProperties;
+ private final DeviceConfigProxy mDeviceConfigProxy;
SparseBooleanArray mBooleanCache = new SparseBooleanArray();
SparseArray<String> mStringCache = new SparseArray<>();
@@ -51,9 +54,11 @@ public class FeatureFlagsRelease implements FeatureFlags, Dumpable {
public FeatureFlagsRelease(
@Main Resources resources,
SystemPropertiesHelper systemProperties,
+ DeviceConfigProxy deviceConfigProxy,
DumpManager dumpManager) {
mResources = resources;
mSystemProperties = systemProperties;
+ mDeviceConfigProxy = deviceConfigProxy;
dumpManager.registerDumpable("SysUIFlags", this);
}
@@ -79,6 +84,18 @@ public class FeatureFlagsRelease implements FeatureFlags, Dumpable {
}
@Override
+ public boolean isEnabled(@NonNull DeviceConfigBooleanFlag flag) {
+ int cacheIndex = mBooleanCache.indexOfKey(flag.getId());
+ if (cacheIndex < 0) {
+ boolean deviceConfigValue = mDeviceConfigProxy.getBoolean(flag.getNamespace(),
+ flag.getName(), flag.getDefault());
+ return isEnabled(flag.getId(), deviceConfigValue);
+ }
+
+ return mBooleanCache.valueAt(cacheIndex);
+ }
+
+ @Override
public boolean isEnabled(SysPropBooleanFlag flag) {
int cacheIndex = mBooleanCache.indexOfKey(flag.getId());
if (cacheIndex < 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 37d4b5061760..2d9d759cba95 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -16,6 +16,8 @@
package com.android.systemui.flags;
+import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
+
import com.android.internal.annotations.Keep;
import com.android.systemui.R;
@@ -173,6 +175,11 @@ public class Flags {
public static final SysPropBooleanFlag BUBBLES_HOME_GESTURE =
new SysPropBooleanFlag(1101, "persist.wm.debug.bubbles_home_gesture", true);
+ @Keep
+ public static final DeviceConfigBooleanFlag WM_ENABLE_PARTIAL_SCREEN_SHARING =
+ new DeviceConfigBooleanFlag(1102, "record_task_content",
+ NAMESPACE_WINDOW_MANAGER, false, true);
+
// 1200 - predictive back
@Keep
public static final SysPropBooleanFlag WM_ENABLE_PREDICTIVE_BACK = new SysPropBooleanFlag(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
index b43856aae4cf..51f3404a9bca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.util.DeviceConfigProxyFake
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
@@ -75,6 +76,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
private lateinit var broadcastReceiver: BroadcastReceiver
private lateinit var clearCacheAction: Consumer<Int>
+ private val deviceConfig = DeviceConfigProxyFake()
private val teamfoodableFlagA = BooleanFlag(500, false, true)
private val teamfoodableFlagB = BooleanFlag(501, true, true)
@@ -90,6 +92,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
systemProperties,
resources,
dumpManager,
+ deviceConfig,
flagMap,
commandRegistry,
barService
@@ -195,6 +198,21 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
}
@Test
+ fun testReadDeviceConfigBooleanFlag() {
+ val namespace = "test_namespace"
+ deviceConfig.setProperty(namespace, "a", "true", false)
+ deviceConfig.setProperty(namespace, "b", "false", false)
+ deviceConfig.setProperty(namespace, "c", null, false)
+
+ assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(1, "a", namespace)))
+ .isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(2, "b", namespace)))
+ .isFalse()
+ assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(3, "c", namespace)))
+ .isFalse()
+ }
+
+ @Test
fun testReadStringFlag() {
whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
index b5deb0b55e11..6b683f456ea7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
@@ -20,6 +20,7 @@ import android.content.res.Resources
import android.test.suitebuilder.annotation.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.DeviceConfigProxyFake
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -44,10 +45,13 @@ class FeatureFlagsReleaseTest : SysuiTestCase() {
@Mock private lateinit var mSystemProperties: SystemPropertiesHelper
@Mock private lateinit var mDumpManager: DumpManager
+ private val deviceConfig = DeviceConfigProxyFake()
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, mDumpManager)
+ mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, deviceConfig,
+ mDumpManager)
}
@After
@@ -85,6 +89,21 @@ class FeatureFlagsReleaseTest : SysuiTestCase() {
}
@Test
+ fun testReadDeviceConfigBooleanFlag() {
+ val namespace = "test_namespace"
+ deviceConfig.setProperty(namespace, "a", "true", false)
+ deviceConfig.setProperty(namespace, "b", "false", false)
+ deviceConfig.setProperty(namespace, "c", null, false)
+
+ assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(1, "a", namespace)))
+ .isTrue()
+ assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(2, "b", namespace)))
+ .isFalse()
+ assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(3, "c", namespace)))
+ .isFalse()
+ }
+
+ @Test
fun testSysPropBooleanFlag() {
val flagId = 213
val flagName = "sys_prop_flag"