summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dave Mankoff <mankoff@google.com> 2022-03-20 21:45:24 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-03-20 21:45:24 +0000
commitc5a0cfad3e3e7838a780b1d16b47a47480812812 (patch)
tree028ba16faaf3a761f4d5f9ebfbcd339feaa38ee3
parentb2f938bf12e8d4cd5bf15561f15d1d58b4d7d540 (diff)
parent214c0014ef4f12b93d9ef33f0a94f1312cce7f50 (diff)
Merge "Add support for TEAMFOOD flag." into tm-dev
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt46
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt4
-rw-r--r--packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt47
5 files changed, 116 insertions, 38 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 6ad91612f99b..19a53091b35c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -24,6 +24,7 @@ import android.os.Parcelable
interface Flag<T> {
val id: Int
+ val teamfood: Boolean
}
interface ParcelableFlag<T> : Flag<T>, Parcelable {
@@ -44,7 +45,8 @@ interface SysPropFlag<T> : Flag<T> {
data class BooleanFlag @JvmOverloads constructor(
override val id: Int,
- override val default: Boolean = false
+ override val default: Boolean = false,
+ override val teamfood: Boolean = false
) : ParcelableFlag<Boolean> {
companion object {
@@ -66,20 +68,25 @@ data class BooleanFlag @JvmOverloads constructor(
}
}
-data class ResourceBooleanFlag constructor(
+data class ResourceBooleanFlag @JvmOverloads constructor(
override val id: Int,
- @BoolRes override val resourceId: Int
+ @BoolRes override val resourceId: Int,
+ override val teamfood: Boolean = false
) : ResourceFlag<Boolean>
-data class SysPropBooleanFlag constructor(
+data class SysPropBooleanFlag @JvmOverloads constructor(
override val id: Int,
override val name: String,
override val default: Boolean = false
-) : SysPropFlag<Boolean>
+) : SysPropFlag<Boolean> {
+ // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
+ override val teamfood: Boolean = false
+}
data class StringFlag @JvmOverloads constructor(
override val id: Int,
- override val default: String = ""
+ override val default: String = "",
+ override val teamfood: Boolean = false
) : ParcelableFlag<String> {
companion object {
@JvmField
@@ -100,14 +107,16 @@ data class StringFlag @JvmOverloads constructor(
}
}
-data class ResourceStringFlag constructor(
+data class ResourceStringFlag @JvmOverloads constructor(
override val id: Int,
- @StringRes override val resourceId: Int
+ @StringRes override val resourceId: Int,
+ override val teamfood: Boolean = false
) : ResourceFlag<String>
data class IntFlag @JvmOverloads constructor(
override val id: Int,
- override val default: Int = 0
+ override val default: Int = 0,
+ override val teamfood: Boolean = false
) : ParcelableFlag<Int> {
companion object {
@@ -129,14 +138,16 @@ data class IntFlag @JvmOverloads constructor(
}
}
-data class ResourceIntFlag constructor(
+data class ResourceIntFlag @JvmOverloads constructor(
override val id: Int,
- @IntegerRes override val resourceId: Int
+ @IntegerRes override val resourceId: Int,
+ override val teamfood: Boolean = false
) : ResourceFlag<Int>
data class LongFlag @JvmOverloads constructor(
override val id: Int,
- override val default: Long = 0
+ override val default: Long = 0,
+ override val teamfood: Boolean = false
) : ParcelableFlag<Long> {
companion object {
@@ -160,7 +171,8 @@ data class LongFlag @JvmOverloads constructor(
data class FloatFlag @JvmOverloads constructor(
override val id: Int,
- override val default: Float = 0f
+ override val default: Float = 0f,
+ override val teamfood: Boolean = false
) : ParcelableFlag<Float> {
companion object {
@@ -182,14 +194,16 @@ data class FloatFlag @JvmOverloads constructor(
}
}
-data class ResourceFloatFlag constructor(
+data class ResourceFloatFlag @JvmOverloads constructor(
override val id: Int,
- override val resourceId: Int
+ override val resourceId: Int,
+ override val teamfood: Boolean = false
) : ResourceFlag<Int>
data class DoubleFlag @JvmOverloads constructor(
override val id: Int,
- override val default: Double = 0.0
+ override val default: Double = 0.0,
+ override val teamfood: Boolean = false
) : ParcelableFlag<Double> {
companion object {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
index 149f6e8e7e9e..26e40e1ecad3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
@@ -64,7 +64,7 @@ class FlagManager constructor(
intent.setPackage(RECEIVING_PACKAGE)
return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<Any?> ->
+ completer: CallbackToFutureAdapter.Completer<Collection<Flag<*>>> ->
context.sendOrderedBroadcast(intent, null,
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -79,7 +79,7 @@ class FlagManager constructor(
}
}, null, Activity.RESULT_OK, "extra data", null)
"QueryingFlags"
- } as ListenableFuture<Collection<Flag<*>>>
+ }
}
/**
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index adfc87241460..256028417a1d 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -19,11 +19,12 @@ package com.android.systemui.flags
import android.content.Context
import android.os.Handler
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlagsDebug.ALL_FLAGS
import com.android.systemui.util.settings.SettingsUtilModule
import dagger.Binds
import dagger.Module
import dagger.Provides
-import java.util.function.Supplier
+import javax.inject.Named
@Module(includes = [
SettingsUtilModule::class
@@ -42,6 +43,7 @@ abstract class FlagsModule {
@JvmStatic
@Provides
- fun providesFlagCollector(): Supplier<Map<Int, Flag<*>>>? = null
+ @Named(ALL_FLAGS)
+ fun providesAllFlags(): Map<Int, Flag<*>> = Flags.collectFlags()
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index 0c5f7ebb6e16..3335c8d62f46 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -50,9 +50,9 @@ import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.function.Consumer;
-import java.util.function.Supplier;
import javax.inject.Inject;
+import javax.inject.Named;
/**
* Concrete implementation of the a Flag manager that returns default values for debug builds
@@ -66,12 +66,13 @@ import javax.inject.Inject;
@SysUISingleton
public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
private static final String TAG = "SysUIFlags";
+ static final String ALL_FLAGS = "all_flags";
private final FlagManager mFlagManager;
private final SecureSettings mSecureSettings;
private final Resources mResources;
private final SystemPropertiesHelper mSystemProperties;
- private final Supplier<Map<Integer, Flag<?>>> mFlagsCollector;
+ private final Map<Integer, Flag<?>> mAllFlags;
private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
private final IStatusBarService mBarService;
@@ -84,13 +85,13 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
SystemPropertiesHelper systemProperties,
@Main Resources resources,
DumpManager dumpManager,
- @Nullable Supplier<Map<Integer, Flag<?>>> flagsCollector,
+ @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
IStatusBarService barService) {
mFlagManager = flagManager;
mSecureSettings = secureSettings;
mResources = resources;
mSystemProperties = systemProperties;
- mFlagsCollector = flagsCollector != null ? flagsCollector : Flags::collectFlags;
+ mAllFlags = allFlags;
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SET_FLAG);
filter.addAction(ACTION_GET_FLAGS);
@@ -107,7 +108,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
int id = flag.getId();
if (!mBooleanFlagCache.containsKey(id)) {
mBooleanFlagCache.put(id,
- readFlagValue(id, flag.getDefault(), BooleanFlagSerializer.INSTANCE));
+ readFlagValue(id, flag.getDefault()));
}
return mBooleanFlagCache.get(id);
@@ -118,8 +119,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
int id = flag.getId();
if (!mBooleanFlagCache.containsKey(id)) {
mBooleanFlagCache.put(id,
- readFlagValue(id, mResources.getBoolean(flag.getResourceId()),
- BooleanFlagSerializer.INSTANCE));
+ readFlagValue(id, mResources.getBoolean(flag.getResourceId())));
}
return mBooleanFlagCache.get(id);
@@ -129,8 +129,13 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
public boolean isEnabled(@NonNull SysPropBooleanFlag flag) {
int id = flag.getId();
if (!mBooleanFlagCache.containsKey(id)) {
+ // Use #readFlagValue to get the default. That will allow it to fall through to
+ // teamfood if need be.
mBooleanFlagCache.put(
- id, mSystemProperties.getBoolean(flag.getName(), flag.getDefault()));
+ id,
+ mSystemProperties.getBoolean(
+ flag.getName(),
+ readFlagValue(id, flag.getDefault())));
}
return mBooleanFlagCache.get(id);
@@ -161,6 +166,19 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
return mStringFlagCache.get(id);
}
+ /** Specific override for Boolean flags that checks against the teamfood list.*/
+ private boolean readFlagValue(int id, boolean defaultValue) {
+ Boolean result = readFlagValueInternal(id, BooleanFlagSerializer.INSTANCE);
+ // Only check for teamfood if the default is false.
+ if (!defaultValue && result == null && id != Flags.TEAMFOOD.getId()) {
+ if (mAllFlags.containsKey(id) && mAllFlags.get(id).getTeamfood()) {
+ return isEnabled(Flags.TEAMFOOD);
+ }
+ }
+
+ return result == null ? defaultValue : result;
+ }
+
@NonNull
private <T> T readFlagValue(int id, @NonNull T defaultValue, FlagSerializer<T> serializer) {
requireNonNull(defaultValue, "defaultValue");
@@ -266,8 +284,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
if (ACTION_SET_FLAG.equals(action)) {
handleSetFlag(intent.getExtras());
} else if (ACTION_GET_FLAGS.equals(action)) {
- Map<Integer, Flag<?>> knownFlagMap = mFlagsCollector.get();
- ArrayList<Flag<?>> flags = new ArrayList<>(knownFlagMap.values());
+ ArrayList<Flag<?>> flags = new ArrayList<>(mAllFlags.values());
// Convert all flags to parcelable flags.
ArrayList<ParcelableFlag<?>> pFlags = new ArrayList<>();
@@ -296,12 +313,11 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
return;
}
- Map<Integer, Flag<?>> flagMap = mFlagsCollector.get();
- if (!flagMap.containsKey(id)) {
+ if (!mAllFlags.containsKey(id)) {
Log.w(TAG, "Tried to set unknown id: " + id);
return;
}
- Flag<?> flag = flagMap.get(id);
+ Flag<?> flag = mAllFlags.get(id);
if (!extras.containsKey(EXTRA_VALUE)) {
eraseFlag(flag);
@@ -338,13 +354,16 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
@Nullable
private ParcelableFlag<?> toParcelableFlag(Flag<?> f) {
if (f instanceof BooleanFlag) {
- return new BooleanFlag(f.getId(), isEnabled((BooleanFlag) f));
+ return new BooleanFlag(f.getId(), isEnabled((BooleanFlag) f), f.getTeamfood());
}
if (f instanceof ResourceBooleanFlag) {
- return new BooleanFlag(f.getId(), isEnabled((ResourceBooleanFlag) f));
+ return new BooleanFlag(
+ f.getId(), isEnabled((ResourceBooleanFlag) f), f.getTeamfood());
}
if (f instanceof SysPropBooleanFlag) {
- return new BooleanFlag(f.getId(), isEnabled((SysPropBooleanFlag) f));
+ // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
+ return new BooleanFlag(
+ f.getId(), isEnabled((SysPropBooleanFlag) f), false);
}
// TODO: add support for other flag types.
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 23a5b2b2c5b7..50b779cb6bf5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -67,9 +67,14 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
private lateinit var mBroadcastReceiver: BroadcastReceiver
private lateinit var mClearCacheAction: Consumer<Int>
+ private val teamfoodableFlagA = BooleanFlag(500, false, true)
+ private val teamfoodableFlagB = BooleanFlag(501, true, true)
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ mFlagMap.put(teamfoodableFlagA.id, teamfoodableFlagA)
+ mFlagMap.put(teamfoodableFlagB.id, teamfoodableFlagB)
mFeatureFlagsDebug = FeatureFlagsDebug(
mFlagManager,
mMockContext,
@@ -77,7 +82,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
mSystemProperties,
mResources,
mDumpManager,
- { mFlagMap },
+ mFlagMap,
mBarService
)
verify(mFlagManager).onSettingsChangedAction = any()
@@ -93,12 +98,50 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testReadBooleanFlag() {
+ // Remember that the TEAMFOOD flag is id#1 and has special behavior.
whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
whenever(mFlagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
- assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(1, false))).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse()
+ assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(5, false))).isFalse()
+ }
+
+ @Test
+ fun testTeamFoodFlag_False() {
+ whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false)
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse()
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
+
+ // Regular boolean flags should still test the same.
+ // Only our teamfoodableFlag should change.
+ testReadBooleanFlag()
+ }
+
+ @Test
+ fun testTeamFoodFlag_True() {
+ whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
+
+ // Regular boolean flags should still test the same.
+ // Only our teamfoodableFlag should change.
+ testReadBooleanFlag()
+ }
+
+ @Test
+ fun testTeamFoodFlag_Overridden() {
+ whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
+ .thenReturn(true)
+ whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
+ .thenReturn(false)
+ whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse()
+
+ // Regular boolean flags should still test the same.
+ // Only our teamfoodableFlag should change.
+ testReadBooleanFlag()
}
@Test