diff options
| author | 2022-03-20 21:45:24 +0000 | |
|---|---|---|
| committer | 2022-03-20 21:45:24 +0000 | |
| commit | c5a0cfad3e3e7838a780b1d16b47a47480812812 (patch) | |
| tree | 028ba16faaf3a761f4d5f9ebfbcd339feaa38ee3 | |
| parent | b2f938bf12e8d4cd5bf15561f15d1d58b4d7d540 (diff) | |
| parent | 214c0014ef4f12b93d9ef33f0a94f1312cce7f50 (diff) | |
Merge "Add support for TEAMFOOD flag." into tm-dev
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 |