diff options
16 files changed, 560 insertions, 361 deletions
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 15847be1295b..0fc82b602d36 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -116,7 +116,6 @@ android_library { "androidx.exifinterface_exifinterface", "androidx.test.ext.junit", "com.google.android.material_material", - "kotlin-reflect", "kotlinx_coroutines_android", "kotlinx_coroutines", "iconloader_base", 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 39283047300b..196f7f05d20d 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt @@ -63,9 +63,9 @@ interface SysPropFlag<T> : Flag<T> { // Consider using the "parcelize" kotlin library. abstract class BooleanFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val default: Boolean = false, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false, override val overridden: Boolean = false ) : ParcelableFlag<Boolean> { @@ -80,6 +80,8 @@ abstract class BooleanFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readBoolean(), teamfood = parcel.readBoolean(), overridden = parcel.readBoolean() @@ -87,6 +89,8 @@ abstract class BooleanFlag constructor( override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeBoolean(default) parcel.writeBoolean(teamfood) parcel.writeBoolean(overridden) @@ -100,11 +104,11 @@ abstract class BooleanFlag constructor( */ data class UnreleasedFlag constructor( override val id: Int, - override val name: String = "", - override val namespace: String = "", + override val name: String, + override val namespace: String, override val teamfood: Boolean = false, override val overridden: Boolean = false -) : BooleanFlag(id, false, name, namespace, teamfood, overridden) +) : BooleanFlag(id, name, namespace, false, teamfood, overridden) /** * A Flag that is true by default. @@ -113,11 +117,11 @@ data class UnreleasedFlag constructor( */ data class ReleasedFlag constructor( override val id: Int, - override val name: String = "", - override val namespace: String = "", + override val name: String, + override val namespace: String, override val teamfood: Boolean = false, override val overridden: Boolean = false -) : BooleanFlag(id, true, name, namespace, teamfood, overridden) +) : BooleanFlag(id, name, namespace, true, teamfood, overridden) /** * A Flag that reads its default values from a resource overlay instead of code. @@ -126,9 +130,9 @@ data class ReleasedFlag constructor( */ data class ResourceBooleanFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, @BoolRes override val resourceId: Int, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false ) : ResourceFlag<Boolean> @@ -157,8 +161,8 @@ data class DeviceConfigBooleanFlag constructor( data class SysPropBooleanFlag constructor( override val id: Int, override val name: String, + override val namespace: String, override val default: Boolean = false, - override val namespace: String = "" ) : SysPropFlag<Boolean> { // TODO(b/223379190): Teamfood not supported for sysprop flags yet. override val teamfood: Boolean = false @@ -166,9 +170,9 @@ data class SysPropBooleanFlag constructor( data class StringFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val default: String = "", - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false, override val overridden: Boolean = false ) : ParcelableFlag<String> { @@ -182,28 +186,32 @@ data class StringFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readString() ?: "" ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeString(default) } } data class ResourceStringFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, @StringRes override val resourceId: Int, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false ) : ResourceFlag<String> data class IntFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val default: Int = 0, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false, override val overridden: Boolean = false ) : ParcelableFlag<Int> { @@ -218,20 +226,24 @@ data class IntFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readInt() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeInt(default) } } data class ResourceIntFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, @IntegerRes override val resourceId: Int, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false ) : ResourceFlag<Int> @@ -239,8 +251,8 @@ data class LongFlag constructor( override val id: Int, override val default: Long = 0, override val teamfood: Boolean = false, - override val name: String = "", - override val namespace: String = "", + override val name: String, + override val namespace: String, override val overridden: Boolean = false ) : ParcelableFlag<Long> { @@ -254,20 +266,24 @@ data class LongFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readLong() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeLong(default) } } data class FloatFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val default: Float = 0f, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false, override val overridden: Boolean = false ) : ParcelableFlag<Float> { @@ -282,29 +298,33 @@ data class FloatFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readFloat() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeFloat(default) } } data class ResourceFloatFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val resourceId: Int, - override val name: String = "", - override val namespace: String = "", override val teamfood: Boolean = false, ) : ResourceFlag<Int> data class DoubleFlag constructor( override val id: Int, + override val name: String, + override val namespace: String, override val default: Double = 0.0, override val teamfood: Boolean = false, - override val name: String = "", - override val namespace: String = "", override val overridden: Boolean = false ) : ParcelableFlag<Double> { @@ -318,11 +338,15 @@ data class DoubleFlag constructor( private constructor(parcel: Parcel) : this( id = parcel.readInt(), + name = parcel.readString(), + namespace = parcel.readString(), default = parcel.readDouble() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(name) + parcel.writeString(namespace) parcel.writeDouble(default) } } diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt new file mode 100644 index 000000000000..74519c21820b --- /dev/null +++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.annotation.BoolRes + +object FlagsFactory { + private val flagMap = mutableMapOf<String, Flag<*>>() + + val knownFlags: Map<String, Flag<*>> + get() = flagMap + + fun unreleasedFlag( + id: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): UnreleasedFlag { + val flag = UnreleasedFlag(id = id, name = name, namespace = namespace, teamfood = teamfood) + FlagsFactory.checkForDupesAndAdd(flag) + return flag + } + + fun releasedFlag( + id: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): ReleasedFlag { + val flag = ReleasedFlag(id = id, name = name, namespace = namespace, teamfood = teamfood) + FlagsFactory.checkForDupesAndAdd(flag) + return flag + } + + fun resourceBooleanFlag( + id: Int, + @BoolRes resourceId: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): ResourceBooleanFlag { + val flag = + ResourceBooleanFlag( + id = id, + name = name, + namespace = namespace, + resourceId = resourceId, + teamfood = teamfood + ) + FlagsFactory.checkForDupesAndAdd(flag) + return flag + } + + fun sysPropBooleanFlag( + id: Int, + name: String, + namespace: String = "systemui", + default: Boolean = false + ): SysPropBooleanFlag { + val flag = + SysPropBooleanFlag(id = id, name = name, namespace = "systemui", default = default) + FlagsFactory.checkForDupesAndAdd(flag) + return flag + } + + private fun checkForDupesAndAdd(flag: Flag<*>) { + if (flagMap.containsKey(flag.name)) { + throw IllegalArgumentException("Name {flag.name} is already registered") + } + flagMap.forEach { + if (it.value.id == flag.id) { + throw IllegalArgumentException("Name {flag.id} is already registered") + } + } + flagMap[flag.name] = flag + } +} diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt new file mode 100644 index 000000000000..89c0786af6e3 --- /dev/null +++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.annotation.BoolRes + +object FlagsFactory { + private val flagMap = mutableMapOf<String, Flag<*>>() + + val knownFlags: Map<String, Flag<*>> + get() = flagMap + + fun unreleasedFlag( + id: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): UnreleasedFlag { + // Unreleased flags are always false in this build. + val flag = UnreleasedFlag(id = id, name = "", namespace = "", teamfood = false) + return flag + } + + fun releasedFlag( + id: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): ReleasedFlag { + val flag = ReleasedFlag(id = id, name = name, namespace = namespace, teamfood = teamfood) + flagMap[name] = flag + return flag + } + + fun resourceBooleanFlag( + id: Int, + @BoolRes resourceId: Int, + name: String, + namespace: String = "systemui", + teamfood: Boolean = false + ): ResourceBooleanFlag { + val flag = + ResourceBooleanFlag( + id = id, + name = name, + namespace = namespace, + resourceId = resourceId, + teamfood = teamfood + ) + flagMap[name] = flag + return flag + } + + fun sysPropBooleanFlag( + id: Int, + name: String, + namespace: String = "systemui", + default: Boolean = false + ): SysPropBooleanFlag { + val flag = + SysPropBooleanFlag(id = id, name = name, namespace = namespace, default = default) + flagMap[name] = flag + return flag + } +} diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java index 72aa299e9d72..3c83682210b6 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java @@ -168,10 +168,10 @@ public class FeatureFlagsRelease implements FeatureFlags { @Override public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("can override: false"); - Map<Integer, Flag<?>> knownFlags = Flags.collectFlags(); - for (Map.Entry<Integer, Flag<?>> idToFlag : knownFlags.entrySet()) { - int id = idToFlag.getKey(); - Flag<?> flag = idToFlag.getValue(); + Map<String, Flag<?>> knownFlags = FlagsFactory.INSTANCE.getKnownFlags(); + for (Map.Entry<String, Flag<?>> nameToFlag : knownFlags.entrySet()) { + Flag<?> flag = nameToFlag.getValue(); + int id = flag.getId(); boolean def = false; if (mBooleanCache.indexOfKey(flag.getId()) < 0) { if (flag instanceof SysPropBooleanFlag) { diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java b/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java index ad4b87da0744..b7fc0e41ea69 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java @@ -229,7 +229,7 @@ public class FlagCommand implements Command { } private int flagNameToId(String flagName) { - Map<String, Flag<?>> flagFields = Flags.getFlagFields(); + Map<String, Flag<?>> flagFields = FlagsFactory.INSTANCE.getKnownFlags(); for (String fieldName : flagFields.keySet()) { if (flagName.equals(fieldName)) { return flagFields.get(fieldName).getId(); @@ -240,7 +240,7 @@ public class FlagCommand implements Command { } private void printKnownFlags(PrintWriter pw) { - Map<String, Flag<?>> fields = Flags.getFlagFields(); + Map<String, Flag<?>> fields = FlagsFactory.INSTANCE.getKnownFlags(); int longestFieldName = 0; for (String fieldName : fields.keySet()) { diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index d012bc95ded2..99dfefa4fa41 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -17,12 +17,11 @@ package com.android.systemui.flags import android.provider.DeviceConfig import com.android.internal.annotations.Keep -import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R -import kotlin.reflect.KClass -import kotlin.reflect.full.declaredMembers -import kotlin.reflect.full.isSubclassOf -import kotlin.reflect.full.staticProperties +import com.android.systemui.flags.FlagsFactory.releasedFlag +import com.android.systemui.flags.FlagsFactory.resourceBooleanFlag +import com.android.systemui.flags.FlagsFactory.sysPropBooleanFlag +import com.android.systemui.flags.FlagsFactory.unreleasedFlag /** * List of [Flag] objects for use in SystemUI. @@ -37,41 +36,51 @@ import kotlin.reflect.full.staticProperties * See [FeatureFlagsDebug] for instructions on flipping the flags via adb. */ object Flags { - @JvmField val TEAMFOOD = UnreleasedFlag(1) + @JvmField val TEAMFOOD = unreleasedFlag(1, "teamfood") // 100 - notification // TODO(b/254512751): Tracking Bug - val NOTIFICATION_PIPELINE_DEVELOPER_LOGGING = UnreleasedFlag(103) + val NOTIFICATION_PIPELINE_DEVELOPER_LOGGING = + unreleasedFlag(103, "notification_pipeline_developer_logging") // TODO(b/254512732): Tracking Bug - @JvmField val NSSL_DEBUG_LINES = UnreleasedFlag(105) + @JvmField val NSSL_DEBUG_LINES = unreleasedFlag(105, "nssl_debug_lines") // TODO(b/254512505): Tracking Bug - @JvmField val NSSL_DEBUG_REMOVE_ANIMATION = UnreleasedFlag(106) + @JvmField val NSSL_DEBUG_REMOVE_ANIMATION = unreleasedFlag(106, "nssl_debug_remove_animation") // TODO(b/254512624): Tracking Bug @JvmField val NOTIFICATION_DRAG_TO_CONTENTS = - ResourceBooleanFlag(108, R.bool.config_notificationToContents) + resourceBooleanFlag( + 108, + R.bool.config_notificationToContents, + "notification_drag_to_contents" + ) // TODO(b/254512517): Tracking Bug - val FSI_REQUIRES_KEYGUARD = UnreleasedFlag(110, teamfood = true) + val FSI_REQUIRES_KEYGUARD = unreleasedFlag(110, "fsi_requires_keyguard", teamfood = true) // TODO(b/254512538): Tracking Bug - val INSTANT_VOICE_REPLY = UnreleasedFlag(111, teamfood = true) + val INSTANT_VOICE_REPLY = unreleasedFlag(111, "instant_voice_reply", teamfood = true) // TODO(b/254512425): Tracking Bug - val NOTIFICATION_MEMORY_MONITOR_ENABLED = ReleasedFlag(112) + val NOTIFICATION_MEMORY_MONITOR_ENABLED = + releasedFlag(112, "notification_memory_monitor_enabled") // TODO(b/254512731): Tracking Bug - @JvmField val NOTIFICATION_DISMISSAL_FADE = UnreleasedFlag(113, teamfood = true) - val STABILITY_INDEX_FIX = UnreleasedFlag(114, teamfood = true) - val SEMI_STABLE_SORT = UnreleasedFlag(115, teamfood = true) + @JvmField + val NOTIFICATION_DISMISSAL_FADE = + unreleasedFlag(113, "notification_dismissal_fade", teamfood = true) + val STABILITY_INDEX_FIX = unreleasedFlag(114, "stability_index_fix", teamfood = true) + val SEMI_STABLE_SORT = unreleasedFlag(115, "semi_stable_sort", teamfood = true) - @JvmField val NOTIFICATION_GROUP_CORNER = UnreleasedFlag(116, teamfood = true) + @JvmField + val NOTIFICATION_GROUP_CORNER = + unreleasedFlag(116, "notification_group_corner", teamfood = true) // TODO(b/257506350): Tracking Bug - val FSI_CHROME = UnreleasedFlag(117) + val FSI_CHROME = unreleasedFlag(117, "fsi_chrome") // next id: 118 @@ -80,25 +89,27 @@ object Flags { // public static final BooleanFlag KEYGUARD_LAYOUT = // new BooleanFlag(200, true); // TODO(b/254512713): Tracking Bug - @JvmField val LOCKSCREEN_ANIMATIONS = ReleasedFlag(201) + @JvmField val LOCKSCREEN_ANIMATIONS = releasedFlag(201, "lockscreen_animations") // TODO(b/254512750): Tracking Bug - val NEW_UNLOCK_SWIPE_ANIMATION = ReleasedFlag(202) - val CHARGING_RIPPLE = ResourceBooleanFlag(203, R.bool.flag_charging_ripple) + val NEW_UNLOCK_SWIPE_ANIMATION = releasedFlag(202, "new_unlock_swipe_animation") + val CHARGING_RIPPLE = resourceBooleanFlag(203, R.bool.flag_charging_ripple, "charging_ripple") // TODO(b/254512281): Tracking Bug @JvmField - val BOUNCER_USER_SWITCHER = ResourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher) + val BOUNCER_USER_SWITCHER = + resourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher, "bouncer_user_switcher") // TODO(b/254512676): Tracking Bug - @JvmField val LOCKSCREEN_CUSTOM_CLOCKS = UnreleasedFlag(207, teamfood = true) + @JvmField + val LOCKSCREEN_CUSTOM_CLOCKS = unreleasedFlag(207, "lockscreen_custom_clocks", teamfood = true) /** * Flag to enable the usage of the new bouncer data source. This is a refactor of and eventual * replacement of KeyguardBouncer.java. */ // TODO(b/254512385): Tracking Bug - @JvmField val MODERN_BOUNCER = ReleasedFlag(208) + @JvmField val MODERN_BOUNCER = releasedFlag(208, "modern_bouncer") /** * Whether the user interactor and repository should use `UserSwitcherController`. @@ -107,7 +118,8 @@ object Flags { * framework APIs. */ // TODO(b/254513286): Tracking Bug - val USER_INTERACTOR_AND_REPO_USE_CONTROLLER = UnreleasedFlag(210) + val USER_INTERACTOR_AND_REPO_USE_CONTROLLER = + unreleasedFlag(210, "user_interactor_and_repo_use_controller") /** * Whether `UserSwitcherController` should use the user interactor. @@ -119,24 +131,24 @@ object Flags { * would created a cycle between controller -> interactor -> controller. */ // TODO(b/254513102): Tracking Bug - val USER_CONTROLLER_USES_INTERACTOR = ReleasedFlag(211) + val USER_CONTROLLER_USES_INTERACTOR = releasedFlag(211, "user_controller_uses_interactor") /** * Whether the clock on a wide lock screen should use the new "stepping" animation for moving * the digits when the clock moves. */ - @JvmField val STEP_CLOCK_ANIMATION = UnreleasedFlag(212) + @JvmField val STEP_CLOCK_ANIMATION = unreleasedFlag(212, "step_clock_animation") /** * Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository * will occur in stages. This is one stage of many to come. */ // TODO(b/255607168): Tracking Bug - @JvmField val DOZING_MIGRATION_1 = UnreleasedFlag(213) + @JvmField val DOZING_MIGRATION_1 = unreleasedFlag(213, "dozing_migration_1") - @JvmField val NEW_ELLIPSE_DETECTION = UnreleasedFlag(214) + @JvmField val NEW_ELLIPSE_DETECTION = unreleasedFlag(214, "new_ellipse_detection") - @JvmField val NEW_UDFPS_OVERLAY = UnreleasedFlag(215) + @JvmField val NEW_UDFPS_OVERLAY = unreleasedFlag(215, "new_udfps_overlay") /** * Whether to enable the code powering customizable lock screen quick affordances. @@ -144,134 +156,152 @@ object Flags { * Note that this flag does not enable individual implementations of quick affordances like the * new camera quick affordance. Look for individual flags for those. */ - @JvmField val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES = UnreleasedFlag(216, teamfood = false) + @JvmField + val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES = + unreleasedFlag(216, "customizable_lock_screen_quick_affordances", teamfood = false) // 300 - power menu // TODO(b/254512600): Tracking Bug - @JvmField val POWER_MENU_LITE = ReleasedFlag(300) + @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite") // 400 - smartspace // TODO(b/254513100): Tracking Bug - val SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED = ReleasedFlag(401) - val SMARTSPACE = ResourceBooleanFlag(402, R.bool.flag_smartspace) + val SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED = + releasedFlag(401, "smartspace_shared_element_transition_enabled") + val SMARTSPACE = resourceBooleanFlag(402, R.bool.flag_smartspace, "smartspace") // 500 - quick settings // TODO(b/254512321): Tracking Bug - @JvmField val COMBINED_QS_HEADERS = ReleasedFlag(501) - val PEOPLE_TILE = ResourceBooleanFlag(502, R.bool.flag_conversations) + @JvmField val COMBINED_QS_HEADERS = releasedFlag(501, "combined_qs_headers") + val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile") @JvmField val QS_USER_DETAIL_SHORTCUT = - ResourceBooleanFlag(503, R.bool.flag_lockscreen_qs_user_detail_shortcut) + resourceBooleanFlag( + 503, + R.bool.flag_lockscreen_qs_user_detail_shortcut, + "qs_user_detail_shortcut" + ) // TODO(b/254512747): Tracking Bug - val NEW_HEADER = ReleasedFlag(505) + val NEW_HEADER = releasedFlag(505, "new_header") // TODO(b/254512383): Tracking Bug @JvmField val FULL_SCREEN_USER_SWITCHER = - ResourceBooleanFlag(506, R.bool.config_enableFullscreenUserSwitcher) + resourceBooleanFlag( + 506, + R.bool.config_enableFullscreenUserSwitcher, + "full_screen_user_switcher" + ) // TODO(b/254512678): Tracking Bug - @JvmField val NEW_FOOTER_ACTIONS = ReleasedFlag(507) + @JvmField val NEW_FOOTER_ACTIONS = releasedFlag(507, "new_footer_actions") // TODO(b/244064524): Tracking Bug - @JvmField val QS_SECONDARY_DATA_SUB_INFO = UnreleasedFlag(508, teamfood = true) + @JvmField + val QS_SECONDARY_DATA_SUB_INFO = + unreleasedFlag(508, "qs_secondary_data_sub_info", teamfood = true) // 600- status bar // TODO(b/254513246): Tracking Bug - val STATUS_BAR_USER_SWITCHER = ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip) + val STATUS_BAR_USER_SWITCHER = + resourceBooleanFlag(602, R.bool.flag_user_switcher_chip, "status_bar_user_switcher") // TODO(b/254512623): Tracking Bug @Deprecated("Replaced by mobile and wifi specific flags.") - val NEW_STATUS_BAR_PIPELINE_BACKEND = UnreleasedFlag(604, teamfood = false) + val NEW_STATUS_BAR_PIPELINE_BACKEND = + unreleasedFlag(604, "new_status_bar_pipeline_backend", teamfood = false) // TODO(b/254512660): Tracking Bug @Deprecated("Replaced by mobile and wifi specific flags.") - val NEW_STATUS_BAR_PIPELINE_FRONTEND = UnreleasedFlag(605, teamfood = false) + val NEW_STATUS_BAR_PIPELINE_FRONTEND = + unreleasedFlag(605, "new_status_bar_pipeline_frontend", teamfood = false) // TODO(b/256614753): Tracking Bug - val NEW_STATUS_BAR_MOBILE_ICONS = UnreleasedFlag(606) + val NEW_STATUS_BAR_MOBILE_ICONS = unreleasedFlag(606, "new_status_bar_mobile_icons") // TODO(b/256614210): Tracking Bug - val NEW_STATUS_BAR_WIFI_ICON = UnreleasedFlag(607) + val NEW_STATUS_BAR_WIFI_ICON = unreleasedFlag(607, "new_status_bar_wifi_icon") // TODO(b/256614751): Tracking Bug - val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND = UnreleasedFlag(608) + val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND = + unreleasedFlag(608, "new_status_bar_mobile_icons_backend") // TODO(b/256613548): Tracking Bug - val NEW_STATUS_BAR_WIFI_ICON_BACKEND = UnreleasedFlag(609) + val NEW_STATUS_BAR_WIFI_ICON_BACKEND = unreleasedFlag(609, "new_status_bar_wifi_icon_backend") // 700 - dialer/calls // TODO(b/254512734): Tracking Bug - val ONGOING_CALL_STATUS_BAR_CHIP = ReleasedFlag(700) + val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip") // TODO(b/254512681): Tracking Bug - val ONGOING_CALL_IN_IMMERSIVE = ReleasedFlag(701) + val ONGOING_CALL_IN_IMMERSIVE = releasedFlag(701, "ongoing_call_in_immersive") // TODO(b/254512753): Tracking Bug - val ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP = ReleasedFlag(702) + val ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP = releasedFlag(702, "ongoing_call_in_immersive_chip_tap") // 800 - general visual/theme - @JvmField val MONET = ResourceBooleanFlag(800, R.bool.flag_monet) + @JvmField val MONET = resourceBooleanFlag(800, R.bool.flag_monet, "monet") // 801 - region sampling // TODO(b/254512848): Tracking Bug - val REGION_SAMPLING = UnreleasedFlag(801) + val REGION_SAMPLING = unreleasedFlag(801, "region_sampling") // 802 - wallpaper rendering // TODO(b/254512923): Tracking Bug - @JvmField val USE_CANVAS_RENDERER = ReleasedFlag(802) + @JvmField val USE_CANVAS_RENDERER = unreleasedFlag(802, "use_canvas_renderer") // 803 - screen contents translation // TODO(b/254513187): Tracking Bug - val SCREEN_CONTENTS_TRANSLATION = UnreleasedFlag(803) + val SCREEN_CONTENTS_TRANSLATION = unreleasedFlag(803, "screen_contents_translation") // 804 - monochromatic themes @JvmField - val MONOCHROMATIC_THEMES = SysPropBooleanFlag(804, "persist.sysui.monochromatic", false) + val MONOCHROMATIC_THEMES = + sysPropBooleanFlag(804, "persist.sysui.monochromatic", default = false) // 900 - media // TODO(b/254512697): Tracking Bug - val MEDIA_TAP_TO_TRANSFER = ReleasedFlag(900) + val MEDIA_TAP_TO_TRANSFER = releasedFlag(900, "media_tap_to_transfer") // TODO(b/254512502): Tracking Bug - val MEDIA_SESSION_ACTIONS = UnreleasedFlag(901) + val MEDIA_SESSION_ACTIONS = unreleasedFlag(901, "media_session_actions") // TODO(b/254512726): Tracking Bug - val MEDIA_NEARBY_DEVICES = ReleasedFlag(903) + val MEDIA_NEARBY_DEVICES = releasedFlag(903, "media_nearby_devices") // TODO(b/254512695): Tracking Bug - val MEDIA_MUTE_AWAIT = ReleasedFlag(904) + val MEDIA_MUTE_AWAIT = releasedFlag(904, "media_mute_await") // TODO(b/254512654): Tracking Bug - @JvmField val DREAM_MEDIA_COMPLICATION = UnreleasedFlag(905) + @JvmField val DREAM_MEDIA_COMPLICATION = unreleasedFlag(905, "dream_media_complication") // TODO(b/254512673): Tracking Bug - @JvmField val DREAM_MEDIA_TAP_TO_OPEN = UnreleasedFlag(906) + @JvmField val DREAM_MEDIA_TAP_TO_OPEN = unreleasedFlag(906, "dream_media_tap_to_open") // TODO(b/254513168): Tracking Bug - @JvmField val UMO_SURFACE_RIPPLE = UnreleasedFlag(907) + @JvmField val UMO_SURFACE_RIPPLE = unreleasedFlag(907, "umo_surface_ripple") // 1000 - dock - val SIMULATE_DOCK_THROUGH_CHARGING = ReleasedFlag(1000) + val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging") // TODO(b/254512758): Tracking Bug - @JvmField val ROUNDED_BOX_RIPPLE = ReleasedFlag(1002) + @JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple") // 1100 - windowing @Keep @JvmField val WM_ENABLE_SHELL_TRANSITIONS = - SysPropBooleanFlag(1100, "persist.wm.debug.shell_transit", false) + sysPropBooleanFlag(1100, "persist.wm.debug.shell_transit", default = false) // TODO(b/254513207): Tracking Bug @Keep @JvmField val WM_ENABLE_PARTIAL_SCREEN_SHARING = - UnreleasedFlag( + unreleasedFlag( 1102, name = "record_task_content", namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER, @@ -281,135 +311,101 @@ object Flags { // TODO(b/254512674): Tracking Bug @Keep @JvmField - val HIDE_NAVBAR_WINDOW = SysPropBooleanFlag(1103, "persist.wm.debug.hide_navbar_window", false) + val HIDE_NAVBAR_WINDOW = + sysPropBooleanFlag(1103, "persist.wm.debug.hide_navbar_window", default = false) @Keep @JvmField - val WM_DESKTOP_WINDOWING = SysPropBooleanFlag(1104, "persist.wm.debug.desktop_mode", false) + val WM_DESKTOP_WINDOWING = + sysPropBooleanFlag(1104, "persist.wm.debug.desktop_mode", default = false) @Keep @JvmField - val WM_CAPTION_ON_SHELL = SysPropBooleanFlag(1105, "persist.wm.debug.caption_on_shell", false) + val WM_CAPTION_ON_SHELL = + sysPropBooleanFlag(1105, "persist.wm.debug.caption_on_shell", default = false) @Keep @JvmField val ENABLE_FLING_TO_DISMISS_BUBBLE = - SysPropBooleanFlag(1108, "persist.wm.debug.fling_to_dismiss_bubble", true) + sysPropBooleanFlag(1108, "persist.wm.debug.fling_to_dismiss_bubble", default = true) @Keep @JvmField val ENABLE_FLING_TO_DISMISS_PIP = - SysPropBooleanFlag(1109, "persist.wm.debug.fling_to_dismiss_pip", true) + sysPropBooleanFlag(1109, "persist.wm.debug.fling_to_dismiss_pip", default = true) @Keep @JvmField val ENABLE_PIP_KEEP_CLEAR_ALGORITHM = - SysPropBooleanFlag(1110, "persist.wm.debug.enable_pip_keep_clear_algorithm", false) + sysPropBooleanFlag( + 1110, + "persist.wm.debug.enable_pip_keep_clear_algorithm", + default = false + ) // TODO(b/256873975): Tracking Bug - @JvmField @Keep val WM_BUBBLE_BAR = UnreleasedFlag(1111) + @JvmField @Keep val WM_BUBBLE_BAR = unreleasedFlag(1111, "wm_bubble_bar") // 1200 - predictive back @Keep @JvmField val WM_ENABLE_PREDICTIVE_BACK = - SysPropBooleanFlag(1200, "persist.wm.debug.predictive_back", true) + sysPropBooleanFlag(1200, "persist.wm.debug.predictive_back", default = true) @Keep @JvmField val WM_ENABLE_PREDICTIVE_BACK_ANIM = - SysPropBooleanFlag(1201, "persist.wm.debug.predictive_back_anim", false) + sysPropBooleanFlag(1201, "persist.wm.debug.predictive_back_anim", default = false) @Keep @JvmField val WM_ALWAYS_ENFORCE_PREDICTIVE_BACK = - SysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", false) + sysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", default = false) // TODO(b/254512728): Tracking Bug - @JvmField val NEW_BACK_AFFORDANCE = UnreleasedFlag(1203, teamfood = false) + @JvmField + val NEW_BACK_AFFORDANCE = unreleasedFlag(1203, "new_back_affordance", teamfood = false) // 1300 - screenshots // TODO(b/254512719): Tracking Bug - @JvmField val SCREENSHOT_REQUEST_PROCESSOR = UnreleasedFlag(1300, teamfood = true) + @JvmField + val SCREENSHOT_REQUEST_PROCESSOR = + unreleasedFlag(1300, "screenshot_request_processor", teamfood = true) // TODO(b/254513155): Tracking Bug - @JvmField val SCREENSHOT_WORK_PROFILE_POLICY = UnreleasedFlag(1301) + @JvmField + val SCREENSHOT_WORK_PROFILE_POLICY = unreleasedFlag(1301, "screenshot_work_profile_policy") // 1400 - columbus // TODO(b/254512756): Tracking Bug - val QUICK_TAP_IN_PCC = ReleasedFlag(1400) + val QUICK_TAP_IN_PCC = releasedFlag(1400, "quick_tap_in_pcc") // 1500 - chooser // TODO(b/254512507): Tracking Bug - val CHOOSER_UNBUNDLED = UnreleasedFlag(1500, teamfood = true) + val CHOOSER_UNBUNDLED = unreleasedFlag(1500, "chooser_unbundled", teamfood = true) // 1600 - accessibility - @JvmField val A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS = UnreleasedFlag(1600) + @JvmField + val A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS = + unreleasedFlag(1600, "a11y_floating_menu_fling_spring_animations") // 1700 - clipboard - @JvmField val CLIPBOARD_OVERLAY_REFACTOR = UnreleasedFlag(1700, teamfood = true) - @JvmField val CLIPBOARD_REMOTE_BEHAVIOR = UnreleasedFlag(1701) + @JvmField + val CLIPBOARD_OVERLAY_REFACTOR = + unreleasedFlag(1700, "clipboard_overlay_refactor", teamfood = true) + @JvmField val CLIPBOARD_REMOTE_BEHAVIOR = unreleasedFlag(1701, "clipboard_remote_behavior") // 1800 - shade container - @JvmField val LEAVE_SHADE_OPEN_FOR_BUGREPORT = UnreleasedFlag(1800, teamfood = true) + @JvmField + val LEAVE_SHADE_OPEN_FOR_BUGREPORT = + unreleasedFlag(1800, "leave_shade_open_for_bugreport", teamfood = true) // 1900 - note task - @JvmField val NOTE_TASKS = SysPropBooleanFlag(1900, "persist.sysui.debug.note_tasks") + @JvmField val NOTE_TASKS = sysPropBooleanFlag(1900, "persist.sysui.debug.note_tasks") // 2000 - device controls - @Keep @JvmField val USE_APP_PANELS = UnreleasedFlag(2000, teamfood = true) + @Keep @JvmField val USE_APP_PANELS = unreleasedFlag(2000, "use_app_panels", teamfood = true) // 2100 - Falsing Manager - @JvmField val FALSING_FOR_LONG_TAPS = ReleasedFlag(2100) - - // Pay no attention to the reflection behind the curtain. - // ========================== Curtain ========================== - // | | - // | . . . . . . . . . . . . . . . . . . . | - @JvmStatic - fun collectFlags(): Map<Int, Flag<*>> { - return flagFields.mapKeys { field -> field.value.id } - } - - // | . . . . . . . . . . . . . . . . . . . | - @JvmStatic - val flagFields: Map<String, Flag<*>> - get() = collectFlagsInClass(Flags) - - @VisibleForTesting - fun collectFlagsInClass(instance: Any): Map<String, Flag<*>> { - val cls = instance::class - val javaPropNames = cls.java.fields.map { it.name } - val props = cls.declaredMembers - val staticProps = cls.staticProperties - val staticPropNames = staticProps.map { it.name } - return props - .mapNotNull { property -> - if ((property.returnType.classifier as KClass<*>).isSubclassOf(Flag::class)) { - // Fields with @JvmStatic should be accessed via java mechanisms - if (javaPropNames.contains(property.name)) { - property.name to cls.java.getField(property.name)[null] as Flag<*> - // Fields with @Keep but not @JvmField. Don't do this. - } else if (staticPropNames.contains(property.name)) { - // The below code causes access violation exceptions. I don't know why. - // property.name to (property.call() as Flag<*>) - // property.name to (staticProps.find { it.name == property.name }!! - // .getter.call() as Flag<*>) - throw java.lang.RuntimeException( - "The {$property.name} flag needs @JvmField" - ) - // Everything else. Skip the `get` prefixed fields that kotlin adds. - } else if (property.name.subSequence(0, 3) != "get") { - property.name to (property.call(instance) as Flag<*>) - } else { - null - } - } else { - null - } - } - .toMap() - } - // | | - // \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/ + @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps") } diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt index e1f4944741a0..18d7bcf9b3fc 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt @@ -30,7 +30,7 @@ interface FlagsCommonModule { @Provides @Named(ALL_FLAGS) fun providesAllFlags(): Map<Int, Flag<*>> { - return Flags.collectFlags() + return FlagsFactory.knownFlags.map { it.value.id to it.value }.toMap() } @JvmStatic diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt index 318f2bc1c227..170a70f2fc40 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt @@ -20,7 +20,6 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat -import java.lang.IllegalStateException import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith @@ -29,12 +28,12 @@ import org.junit.runner.RunWith @RunWith(AndroidTestingRunner::class) class FakeFeatureFlagsTest : SysuiTestCase() { - private val unreleasedFlag = UnreleasedFlag(-1000) - private val releasedFlag = ReleasedFlag(-1001) - private val stringFlag = StringFlag(-1002) - private val resourceBooleanFlag = ResourceBooleanFlag(-1003, resourceId = -1) - private val resourceStringFlag = ResourceStringFlag(-1004, resourceId = -1) - private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, name = "test") + private val unreleasedFlag = UnreleasedFlag(-1000, "-1000", "test") + private val releasedFlag = ReleasedFlag(-1001, "-1001", "test") + private val stringFlag = StringFlag(-1002, "-1002", "test") + private val resourceBooleanFlag = ResourceBooleanFlag(-1003, "-1003", "test", resourceId = -1) + private val resourceStringFlag = ResourceStringFlag(-1004, "-1004", "test", resourceId = -1) + private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, "test", "test") /** * FakeFeatureFlags does not honor any default values. All flags which are accessed must be @@ -47,7 +46,7 @@ class FakeFeatureFlagsTest : SysuiTestCase() { assertThat(flags.isEnabled(Flags.TEAMFOOD)).isFalse() fail("Expected an exception when accessing an unspecified flag.") } catch (ex: IllegalStateException) { - assertThat(ex.message).contains("TEAMFOOD") + assertThat(ex.message).contains("id=1") } try { assertThat(flags.isEnabled(unreleasedFlag)).isFalse() 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 456012abc7c6..7592cc527190 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt @@ -57,21 +57,32 @@ import org.mockito.Mockito.`when` as whenever class FeatureFlagsDebugTest : SysuiTestCase() { private lateinit var mFeatureFlagsDebug: FeatureFlagsDebug - @Mock private lateinit var flagManager: FlagManager - @Mock private lateinit var mockContext: Context - @Mock private lateinit var secureSettings: SecureSettings - @Mock private lateinit var systemProperties: SystemPropertiesHelper - @Mock private lateinit var resources: Resources - @Mock private lateinit var commandRegistry: CommandRegistry - @Mock private lateinit var restarter: Restarter + @Mock + private lateinit var flagManager: FlagManager + @Mock + private lateinit var mockContext: Context + @Mock + private lateinit var secureSettings: SecureSettings + @Mock + private lateinit var systemProperties: SystemPropertiesHelper + @Mock + private lateinit var resources: Resources + @Mock + private lateinit var commandRegistry: CommandRegistry + @Mock + private lateinit var restarter: Restarter private val flagMap = mutableMapOf<Int, Flag<*>>() private lateinit var broadcastReceiver: BroadcastReceiver private lateinit var clearCacheAction: Consumer<Int> private val serverFlagReader = ServerFlagReaderFake() private val deviceConfig = DeviceConfigProxyFake() - private val teamfoodableFlagA = UnreleasedFlag(500, teamfood = true) - private val teamfoodableFlagB = ReleasedFlag(501, teamfood = true) + private val teamfoodableFlagA = UnreleasedFlag( + 500, name = "a", namespace = "test", teamfood = true + ) + private val teamfoodableFlagB = ReleasedFlag( + 501, name = "b", namespace = "test", teamfood = true + ) @Before fun setup() { @@ -91,8 +102,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() { mFeatureFlagsDebug.init() verify(flagManager).onSettingsChangedAction = any() broadcastReceiver = withArgCaptor { - verify(mockContext).registerReceiver(capture(), any(), nullable(), nullable(), - any()) + verify(mockContext).registerReceiver( + capture(), any(), nullable(), nullable(), + any() + ) } clearCacheAction = withArgCaptor { verify(flagManager).clearCacheAction = capture() @@ -106,10 +119,42 @@ class FeatureFlagsDebugTest : SysuiTestCase() { whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false) - assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(2))).isTrue() - assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(3))).isTrue() - assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(4))).isFalse() - assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(5))).isFalse() + assertThat( + mFeatureFlagsDebug.isEnabled( + ReleasedFlag( + 2, + name = "2", + namespace = "test" + ) + ) + ).isTrue() + assertThat( + mFeatureFlagsDebug.isEnabled( + UnreleasedFlag( + 3, + name = "3", + namespace = "test" + ) + ) + ).isTrue() + assertThat( + mFeatureFlagsDebug.isEnabled( + ReleasedFlag( + 4, + name = "3", + namespace = "test" + ) + ) + ).isFalse() + assertThat( + mFeatureFlagsDebug.isEnabled( + UnreleasedFlag( + 5, + name = "4", + namespace = "test" + ) + ) + ).isFalse() } @Test @@ -137,9 +182,9 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun teamFoodFlag_Overridden() { whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any())) - .thenReturn(true) + .thenReturn(true) whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any())) - .thenReturn(false) + .thenReturn(false) whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse() @@ -160,17 +205,26 @@ class FeatureFlagsDebugTest : SysuiTestCase() { whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) whenever(flagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false) - assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(1, 1001))).isFalse() - assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(2, 1002))).isTrue() - assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(3, 1003))).isTrue() + assertThat( + mFeatureFlagsDebug.isEnabled( + ResourceBooleanFlag( + 1, + "1", + "test", + 1001 + ) + ) + ).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(2, "2", "test", 1002))).isTrue() + assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(3, "3", "test", 1003))).isTrue() Assert.assertThrows(NameNotFoundException::class.java) { - mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(4, 1004)) + mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(4, "4", "test", 1004)) } // Test that resource is loaded (and validated) even when the setting is set. // This prevents developers from not noticing when they reference an invalid resource. Assert.assertThrows(NameNotFoundException::class.java) { - mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(5, 1005)) + mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(5, "5", "test", 1005)) } } @@ -183,21 +237,30 @@ class FeatureFlagsDebugTest : SysuiTestCase() { return@thenAnswer it.getArgument(1) } - assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(1, "a"))).isFalse() - assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(2, "b"))).isTrue() - assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(3, "c", true))).isTrue() - assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(4, "d", false))).isFalse() - assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(5, "e"))).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(1, "a", "test"))).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(2, "b", "test"))).isTrue() + assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(3, "c", "test", true))).isTrue() + assertThat( + mFeatureFlagsDebug.isEnabled( + SysPropBooleanFlag( + 4, + "d", + "test", + false + ) + ) + ).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(5, "e", "test"))).isFalse() } @Test fun readStringFlag() { whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo") whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar") - assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz") - assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "baz"))).isEqualTo("baz") - assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "buz"))).isEqualTo("foo") - assertThat(mFeatureFlagsDebug.getString(StringFlag(4, "buz"))).isEqualTo("bar") + assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "1", "test", "biz"))).isEqualTo("biz") + assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "2", "test", "baz"))).isEqualTo("baz") + assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "3", "test", "buz"))).isEqualTo("foo") + assertThat(mFeatureFlagsDebug.getString(StringFlag(4, "4", "test", "buz"))).isEqualTo("bar") } @Test @@ -213,20 +276,47 @@ class FeatureFlagsDebugTest : SysuiTestCase() { whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4") whenever(flagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6") - assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(1, 1001))).isEqualTo("") - assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(2, 1002))).isEqualTo("resource2") - assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(3, 1003))).isEqualTo("override3") + assertThat( + mFeatureFlagsDebug.getString( + ResourceStringFlag( + 1, + "1", + "test", + 1001 + ) + ) + ).isEqualTo("") + assertThat( + mFeatureFlagsDebug.getString( + ResourceStringFlag( + 2, + "2", + "test", + 1002 + ) + ) + ).isEqualTo("resource2") + assertThat( + mFeatureFlagsDebug.getString( + ResourceStringFlag( + 3, + "3", + "test", + 1003 + ) + ) + ).isEqualTo("override3") Assert.assertThrows(NullPointerException::class.java) { - mFeatureFlagsDebug.getString(ResourceStringFlag(4, 1004)) + mFeatureFlagsDebug.getString(ResourceStringFlag(4, "4", "test", 1004)) } Assert.assertThrows(NameNotFoundException::class.java) { - mFeatureFlagsDebug.getString(ResourceStringFlag(5, 1005)) + mFeatureFlagsDebug.getString(ResourceStringFlag(5, "5", "test", 1005)) } // Test that resource is loaded (and validated) even when the setting is set. // This prevents developers from not noticing when they reference an invalid resource. Assert.assertThrows(NameNotFoundException::class.java) { - mFeatureFlagsDebug.getString(ResourceStringFlag(6, 1005)) + mFeatureFlagsDebug.getString(ResourceStringFlag(6, "6", "test", 1005)) } } @@ -234,10 +324,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() { fun readIntFlag() { whenever(flagManager.readFlagValue<Int>(eq(3), any())).thenReturn(22) whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(48) - assertThat(mFeatureFlagsDebug.getInt(IntFlag(1, 12))).isEqualTo(12) - assertThat(mFeatureFlagsDebug.getInt(IntFlag(2, 93))).isEqualTo(93) - assertThat(mFeatureFlagsDebug.getInt(IntFlag(3, 8))).isEqualTo(22) - assertThat(mFeatureFlagsDebug.getInt(IntFlag(4, 234))).isEqualTo(48) + assertThat(mFeatureFlagsDebug.getInt(IntFlag(1, "1", "test", 12))).isEqualTo(12) + assertThat(mFeatureFlagsDebug.getInt(IntFlag(2, "2", "test", 93))).isEqualTo(93) + assertThat(mFeatureFlagsDebug.getInt(IntFlag(3, "3", "test", 8))).isEqualTo(22) + assertThat(mFeatureFlagsDebug.getInt(IntFlag(4, "4", "test", 234))).isEqualTo(48) } @Test @@ -253,26 +343,26 @@ class FeatureFlagsDebugTest : SysuiTestCase() { whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(500) whenever(flagManager.readFlagValue<Int>(eq(5), any())).thenReturn(9519) - assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(1, 1001))).isEqualTo(88) - assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(2, 1002))).isEqualTo(61) - assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(3, 1003))).isEqualTo(20) + assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(1, "1", "test", 1001))).isEqualTo(88) + assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(2, "2", "test", 1002))).isEqualTo(61) + assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(3, "3", "test", 1003))).isEqualTo(20) Assert.assertThrows(NotFoundException::class.java) { - mFeatureFlagsDebug.getInt(ResourceIntFlag(4, 1004)) + mFeatureFlagsDebug.getInt(ResourceIntFlag(4, "4", "test", 1004)) } // Test that resource is loaded (and validated) even when the setting is set. // This prevents developers from not noticing when they reference an invalid resource. Assert.assertThrows(NotFoundException::class.java) { - mFeatureFlagsDebug.getInt(ResourceIntFlag(5, 1005)) + mFeatureFlagsDebug.getInt(ResourceIntFlag(5, "5", "test", 1005)) } } @Test fun broadcastReceiver_IgnoresInvalidData() { - addFlag(UnreleasedFlag(1)) - addFlag(ResourceBooleanFlag(2, 1002)) - addFlag(StringFlag(3, "flag3")) - addFlag(ResourceStringFlag(4, 1004)) + addFlag(UnreleasedFlag(1, "1", "test")) + addFlag(ResourceBooleanFlag(2, "2", "test", 1002)) + addFlag(StringFlag(3, "3", "test", "flag3")) + addFlag(ResourceStringFlag(4, "4", "test", 1004)) broadcastReceiver.onReceive(mockContext, null) broadcastReceiver.onReceive(mockContext, Intent()) @@ -288,7 +378,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun intentWithId_NoValueKeyClears() { - addFlag(UnreleasedFlag(1)) + addFlag(UnreleasedFlag(1, name = "1", namespace = "test")) // trying to erase an id not in the map does nothing broadcastReceiver.onReceive( @@ -307,10 +397,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun setBooleanFlag() { - addFlag(UnreleasedFlag(1)) - addFlag(UnreleasedFlag(2)) - addFlag(ResourceBooleanFlag(3, 1003)) - addFlag(ResourceBooleanFlag(4, 1004)) + addFlag(UnreleasedFlag(1, "1", "test")) + addFlag(UnreleasedFlag(2, "2", "test")) + addFlag(ResourceBooleanFlag(3, "3", "test", 1003)) + addFlag(ResourceBooleanFlag(4, "4", "test", 1004)) setByBroadcast(1, false) verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}") @@ -327,8 +417,8 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun setStringFlag() { - addFlag(StringFlag(1, "flag1")) - addFlag(ResourceStringFlag(2, 1002)) + addFlag(StringFlag(1, "flag1", "1", "test")) + addFlag(ResourceStringFlag(2, "2", "test", 1002)) setByBroadcast(1, "override1") verifyPutData(1, "{\"type\":\"string\",\"value\":\"override1\"}") @@ -339,7 +429,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun setFlag_ClearsCache() { - val flag1 = addFlag(StringFlag(1, "flag1")) + val flag1 = addFlag(StringFlag(1, "1", "test", "flag1")) whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original") // gets the flag & cache it @@ -361,7 +451,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun serverSide_Overrides_MakesFalse() { - val flag = ReleasedFlag(100) + val flag = ReleasedFlag(100, "100", "test") serverFlagReader.setFlagValue(flag.namespace, flag.name, false) @@ -370,7 +460,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun serverSide_Overrides_MakesTrue() { - val flag = UnreleasedFlag(100) + val flag = UnreleasedFlag(100, name = "100", namespace = "test") serverFlagReader.setFlagValue(flag.namespace, flag.name, true) @@ -379,13 +469,13 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun dumpFormat() { - val flag1 = ReleasedFlag(1) - val flag2 = ResourceBooleanFlag(2, 1002) - val flag3 = UnreleasedFlag(3) - val flag4 = StringFlag(4, "") - val flag5 = StringFlag(5, "flag5default") - val flag6 = ResourceStringFlag(6, 1006) - val flag7 = ResourceStringFlag(7, 1007) + val flag1 = ReleasedFlag(1, "1", "test") + val flag2 = ResourceBooleanFlag(2, "2", "test", 1002) + val flag3 = UnreleasedFlag(3, "3", "test") + val flag4 = StringFlag(4, "4", "test", "") + val flag5 = StringFlag(5, "5", "test", "flag5default") + val flag6 = ResourceStringFlag(6, "6", "test", 1006) + val flag7 = ResourceStringFlag(7, "7", "test", 1007) whenever(resources.getBoolean(1002)).thenReturn(true) whenever(resources.getString(1006)).thenReturn("resource1006") 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 b10fb86c26ea..d5b5a4a4101e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt @@ -59,7 +59,9 @@ class FeatureFlagsReleaseTest : SysuiTestCase() { fun testBooleanResourceFlag() { val flagId = 213 val flagResourceId = 3 - val flag = ResourceBooleanFlag(flagId, flagResourceId) + val flagName = "213" + val flagNamespace = "test" + val flag = ResourceBooleanFlag(flagId, flagName, flagNamespace, flagResourceId) whenever(mResources.getBoolean(flagResourceId)).thenReturn(true) assertThat(mFeatureFlagsRelease.isEnabled(flag)).isTrue() } @@ -71,14 +73,16 @@ class FeatureFlagsReleaseTest : SysuiTestCase() { whenever(mResources.getString(1003)).thenReturn(null) whenever(mResources.getString(1004)).thenAnswer { throw NameNotFoundException() } - assertThat(mFeatureFlagsRelease.getString(ResourceStringFlag(1, 1001))).isEqualTo("") - assertThat(mFeatureFlagsRelease.getString(ResourceStringFlag(2, 1002))).isEqualTo("res2") + assertThat(mFeatureFlagsRelease.getString( + ResourceStringFlag(1, "1", "test", 1001))).isEqualTo("") + assertThat(mFeatureFlagsRelease.getString( + ResourceStringFlag(2, "2", "test", 1002))).isEqualTo("res2") assertThrows(NullPointerException::class.java) { - mFeatureFlagsRelease.getString(ResourceStringFlag(3, 1003)) + mFeatureFlagsRelease.getString(ResourceStringFlag(3, "3", "test", 1003)) } assertThrows(NameNotFoundException::class.java) { - mFeatureFlagsRelease.getString(ResourceStringFlag(4, 1004)) + mFeatureFlagsRelease.getString(ResourceStringFlag(4, "4", "test", 1004)) } } @@ -86,16 +90,17 @@ class FeatureFlagsReleaseTest : SysuiTestCase() { fun testSysPropBooleanFlag() { val flagId = 213 val flagName = "sys_prop_flag" + val flagNamespace = "test" val flagDefault = true - val flag = SysPropBooleanFlag(flagId, flagName, flagDefault) + val flag = SysPropBooleanFlag(flagId, flagName, flagNamespace, flagDefault) whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault) assertThat(mFeatureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault) } @Test fun serverSide_OverridesReleased_MakesFalse() { - val flag = ReleasedFlag(100) + val flag = ReleasedFlag(100, "100", "test") serverFlagReader.setFlagValue(flag.namespace, flag.name, false) @@ -104,7 +109,7 @@ class FeatureFlagsReleaseTest : SysuiTestCase() { @Test fun serverSide_OverridesUnreleased_Ignored() { - val flag = UnreleasedFlag(100) + val flag = UnreleasedFlag(100, "100", "test") serverFlagReader.setFlagValue(flag.namespace, flag.name, true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt index 7355319a2fbc..fea91c53424d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt @@ -33,10 +33,10 @@ class FlagCommandTest : SysuiTestCase() { @Mock private lateinit var featureFlags: FeatureFlagsDebug @Mock private lateinit var pw: PrintWriter private val flagMap = mutableMapOf<Int, Flag<*>>() - private val flagA = UnreleasedFlag(500) - private val flagB = ReleasedFlag(501) - private val stringFlag = StringFlag(502, "abracadabra") - private val intFlag = IntFlag(503, 12) + private val flagA = UnreleasedFlag(500, "500", "test") + private val flagB = ReleasedFlag(501, "501", "test") + private val stringFlag = StringFlag(502, "502", "test", "abracadabra") + private val intFlag = IntFlag(503, "503", "test", 12) private lateinit var cmd: FlagCommand diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt index 17324a01502b..fca7e96fb148 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt @@ -64,14 +64,14 @@ class FlagManagerTest : SysuiTestCase() { verifyNoMoreInteractions(mFlagSettingsHelper) // adding the first listener registers the observer - mFlagManager.addListener(ReleasedFlag(1), listener1) + mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1) val observer = withArgCaptor<ContentObserver> { verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) } verifyNoMoreInteractions(mFlagSettingsHelper) // adding another listener does nothing - mFlagManager.addListener(ReleasedFlag(2), listener2) + mFlagManager.addListener(ReleasedFlag(2, "2", "test"), listener2) verifyNoMoreInteractions(mFlagSettingsHelper) // removing the original listener does nothing with second one still present @@ -89,7 +89,7 @@ class FlagManagerTest : SysuiTestCase() { val listener = mock<FlagListenable.Listener>() val clearCacheAction = mock<Consumer<Int>>() mFlagManager.clearCacheAction = clearCacheAction - mFlagManager.addListener(ReleasedFlag(1), listener) + mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener) val observer = withArgCaptor<ContentObserver> { verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) } @@ -101,8 +101,8 @@ class FlagManagerTest : SysuiTestCase() { fun testObserverInvokesListeners() { val listener1 = mock<FlagListenable.Listener>() val listener10 = mock<FlagListenable.Listener>() - mFlagManager.addListener(ReleasedFlag(1), listener1) - mFlagManager.addListener(ReleasedFlag(10), listener10) + mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1) + mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener10) val observer = withArgCaptor<ContentObserver> { verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) } @@ -127,8 +127,8 @@ class FlagManagerTest : SysuiTestCase() { fun testOnlySpecificFlagListenerIsInvoked() { val listener1 = mock<FlagListenable.Listener>() val listener10 = mock<FlagListenable.Listener>() - mFlagManager.addListener(ReleasedFlag(1), listener1) - mFlagManager.addListener(ReleasedFlag(10), listener10) + mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1) + mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener10) mFlagManager.dispatchListenersAndMaybeRestart(1, null) val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> { @@ -148,8 +148,8 @@ class FlagManagerTest : SysuiTestCase() { @Test fun testSameListenerCanBeUsedForMultipleFlags() { val listener = mock<FlagListenable.Listener>() - mFlagManager.addListener(ReleasedFlag(1), listener) - mFlagManager.addListener(ReleasedFlag(10), listener) + mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener) + mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener) mFlagManager.dispatchListenersAndMaybeRestart(1, null) val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> { @@ -177,7 +177,7 @@ class FlagManagerTest : SysuiTestCase() { @Test fun testListenerCanSuppressRestart() { val restartAction = mock<Consumer<Boolean>>() - mFlagManager.addListener(ReleasedFlag(1)) { event -> + mFlagManager.addListener(ReleasedFlag(1, "1", "test")) { event -> event.requestNoRestart() } mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) @@ -188,7 +188,7 @@ class FlagManagerTest : SysuiTestCase() { @Test fun testListenerOnlySuppressesRestartForOwnFlag() { val restartAction = mock<Consumer<Boolean>>() - mFlagManager.addListener(ReleasedFlag(10)) { event -> + mFlagManager.addListener(ReleasedFlag(10, "10", "test")) { event -> event.requestNoRestart() } mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) @@ -199,10 +199,10 @@ class FlagManagerTest : SysuiTestCase() { @Test fun testRestartWhenNotAllListenersRequestSuppress() { val restartAction = mock<Consumer<Boolean>>() - mFlagManager.addListener(ReleasedFlag(10)) { event -> + mFlagManager.addListener(ReleasedFlag(10, "10", "test")) { event -> event.requestNoRestart() } - mFlagManager.addListener(ReleasedFlag(10)) { + mFlagManager.addListener(ReleasedFlag(10, "10", "test")) { // do not request } mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.kt deleted file mode 100644 index 2b556f112e5f..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.flags - -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.google.common.truth.Truth -import java.lang.StringBuilder -import java.util.ArrayList -import java.util.HashMap -import org.junit.Test - -@SmallTest -class FlagsTest : SysuiTestCase() { - @Test - fun testDuplicateFlagIdCheckWorks() { - val flags = Flags.collectFlagsInClass(DuplicateFlagContainer) - val duplicates = groupDuplicateFlags(flags) - Truth.assertWithMessage(generateAssertionMessage(duplicates)) - .that(duplicates.size) - .isEqualTo(2) - } - - @Test - fun testNoDuplicateFlagIds() { - val flags = Flags.collectFlagsInClass(Flags) - val duplicates = groupDuplicateFlags(flags) - Truth.assertWithMessage(generateAssertionMessage(duplicates)) - .that(duplicates.size) - .isEqualTo(0) - } - - private fun generateAssertionMessage(duplicates: Map<Int, List<String>>): String { - val stringBuilder = StringBuilder() - stringBuilder.append("Duplicate flag keys found: {") - for (id in duplicates.keys) { - stringBuilder - .append(" ") - .append(id) - .append(": [") - .append(java.lang.String.join(", ", duplicates[id])) - .append("]") - } - stringBuilder.append(" }") - return stringBuilder.toString() - } - - private fun groupDuplicateFlags(flags: Map<String, Flag<*>>): Map<Int, List<String>> { - val grouping: MutableMap<Int, MutableList<String>> = HashMap() - for (flag in flags) { - grouping.putIfAbsent(flag.value.id, ArrayList()) - grouping[flag.value.id]!!.add(flag.key) - } - val result: MutableMap<Int, List<String>> = HashMap() - for (id in grouping.keys) { - if (grouping[id]!!.size > 1) { - result[id] = grouping[id]!! - } - } - return result - } - - private object DuplicateFlagContainer { - val A_FLAG: BooleanFlag = UnreleasedFlag(0) - val B_FLAG: BooleanFlag = UnreleasedFlag(0) - val C_FLAG = StringFlag(0) - val D_FLAG: BooleanFlag = UnreleasedFlag(1) - val E_FLAG = DoubleFlag(3) - val F_FLAG = DoubleFlag(3) - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt index 6f5f460d41c4..1633912abec7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt @@ -50,7 +50,7 @@ class ServerFlagReaderImplTest : SysuiTestCase() { @Test fun testChange_alertsListener() { - val flag = ReleasedFlag(1) + val flag = ReleasedFlag(1, "1", "test") serverFlagReader.listenForChanges(listOf(flag), changeListener) deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt index 6fb9c33ada06..6c82cef22ddb 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt @@ -27,7 +27,7 @@ class FakeFeatureFlags : FeatureFlags { private val listenerFlagIds = mutableMapOf<FlagListenable.Listener, MutableSet<Int>>() init { - Flags.flagFields.forEach { entry: Map.Entry<String, Flag<*>> -> + FlagsFactory.knownFlags.forEach { entry: Map.Entry<String, Flag<*>> -> knownFlagNames[entry.value.id] = entry.key } } |