Merge changes I29bf2065,Ic858826c,I7fe0bd12 into tm-qpr-dev am: 2dcc550cb7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20414824

Change-Id: If053320b02960ffbc57c4d88316e16d3284481f0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Dave Mankoff
2022-11-10 02:04:33 +00:00
committed by Automerger Merge Worker
16 changed files with 560 additions and 361 deletions

View File

@@ -116,7 +116,6 @@ android_library {
"androidx.exifinterface_exifinterface", "androidx.exifinterface_exifinterface",
"androidx.test.ext.junit", "androidx.test.ext.junit",
"com.google.android.material_material", "com.google.android.material_material",
"kotlin-reflect",
"kotlinx_coroutines_android", "kotlinx_coroutines_android",
"kotlinx_coroutines", "kotlinx_coroutines",
"iconloader_base", "iconloader_base",

View File

@@ -63,9 +63,9 @@ interface SysPropFlag<T> : Flag<T> {
// Consider using the "parcelize" kotlin library. // Consider using the "parcelize" kotlin library.
abstract class BooleanFlag constructor( abstract class BooleanFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val default: Boolean = false, override val default: Boolean = false,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<Boolean> { ) : ParcelableFlag<Boolean> {
@@ -80,6 +80,8 @@ abstract class BooleanFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readBoolean(), default = parcel.readBoolean(),
teamfood = parcel.readBoolean(), teamfood = parcel.readBoolean(),
overridden = parcel.readBoolean() overridden = parcel.readBoolean()
@@ -87,6 +89,8 @@ abstract class BooleanFlag constructor(
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeBoolean(default) parcel.writeBoolean(default)
parcel.writeBoolean(teamfood) parcel.writeBoolean(teamfood)
parcel.writeBoolean(overridden) parcel.writeBoolean(overridden)
@@ -100,11 +104,11 @@ abstract class BooleanFlag constructor(
*/ */
data class UnreleasedFlag constructor( data class UnreleasedFlag constructor(
override val id: Int, override val id: Int,
override val name: String = "", override val name: String,
override val namespace: String = "", override val namespace: String,
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: 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. * A Flag that is true by default.
@@ -113,11 +117,11 @@ data class UnreleasedFlag constructor(
*/ */
data class ReleasedFlag constructor( data class ReleasedFlag constructor(
override val id: Int, override val id: Int,
override val name: String = "", override val name: String,
override val namespace: String = "", override val namespace: String,
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: 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. * 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( data class ResourceBooleanFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
@BoolRes override val resourceId: Int, @BoolRes override val resourceId: Int,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false override val teamfood: Boolean = false
) : ResourceFlag<Boolean> ) : ResourceFlag<Boolean>
@@ -157,8 +161,8 @@ data class DeviceConfigBooleanFlag constructor(
data class SysPropBooleanFlag constructor( data class SysPropBooleanFlag constructor(
override val id: Int, override val id: Int,
override val name: String, override val name: String,
override val namespace: String,
override val default: Boolean = false, override val default: Boolean = false,
override val namespace: String = ""
) : SysPropFlag<Boolean> { ) : SysPropFlag<Boolean> {
// TODO(b/223379190): Teamfood not supported for sysprop flags yet. // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
override val teamfood: Boolean = false override val teamfood: Boolean = false
@@ -166,9 +170,9 @@ data class SysPropBooleanFlag constructor(
data class StringFlag constructor( data class StringFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val default: String = "", override val default: String = "",
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<String> { ) : ParcelableFlag<String> {
@@ -182,28 +186,32 @@ data class StringFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readString() ?: "" default = parcel.readString() ?: ""
) )
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeString(default) parcel.writeString(default)
} }
} }
data class ResourceStringFlag constructor( data class ResourceStringFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
@StringRes override val resourceId: Int, @StringRes override val resourceId: Int,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false override val teamfood: Boolean = false
) : ResourceFlag<String> ) : ResourceFlag<String>
data class IntFlag constructor( data class IntFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val default: Int = 0, override val default: Int = 0,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<Int> { ) : ParcelableFlag<Int> {
@@ -218,20 +226,24 @@ data class IntFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readInt() default = parcel.readInt()
) )
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeInt(default) parcel.writeInt(default)
} }
} }
data class ResourceIntFlag constructor( data class ResourceIntFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
@IntegerRes override val resourceId: Int, @IntegerRes override val resourceId: Int,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false override val teamfood: Boolean = false
) : ResourceFlag<Int> ) : ResourceFlag<Int>
@@ -239,8 +251,8 @@ data class LongFlag constructor(
override val id: Int, override val id: Int,
override val default: Long = 0, override val default: Long = 0,
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val name: String = "", override val name: String,
override val namespace: String = "", override val namespace: String,
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<Long> { ) : ParcelableFlag<Long> {
@@ -254,20 +266,24 @@ data class LongFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readLong() default = parcel.readLong()
) )
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeLong(default) parcel.writeLong(default)
} }
} }
data class FloatFlag constructor( data class FloatFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val default: Float = 0f, override val default: Float = 0f,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<Float> { ) : ParcelableFlag<Float> {
@@ -282,29 +298,33 @@ data class FloatFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readFloat() default = parcel.readFloat()
) )
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeFloat(default) parcel.writeFloat(default)
} }
} }
data class ResourceFloatFlag constructor( data class ResourceFloatFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val resourceId: Int, override val resourceId: Int,
override val name: String = "",
override val namespace: String = "",
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
) : ResourceFlag<Int> ) : ResourceFlag<Int>
data class DoubleFlag constructor( data class DoubleFlag constructor(
override val id: Int, override val id: Int,
override val name: String,
override val namespace: String,
override val default: Double = 0.0, override val default: Double = 0.0,
override val teamfood: Boolean = false, override val teamfood: Boolean = false,
override val name: String = "",
override val namespace: String = "",
override val overridden: Boolean = false override val overridden: Boolean = false
) : ParcelableFlag<Double> { ) : ParcelableFlag<Double> {
@@ -318,11 +338,15 @@ data class DoubleFlag constructor(
private constructor(parcel: Parcel) : this( private constructor(parcel: Parcel) : this(
id = parcel.readInt(), id = parcel.readInt(),
name = parcel.readString(),
namespace = parcel.readString(),
default = parcel.readDouble() default = parcel.readDouble()
) )
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id) parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(namespace)
parcel.writeDouble(default) parcel.writeDouble(default)
} }
} }

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -168,10 +168,10 @@ public class FeatureFlagsRelease implements FeatureFlags {
@Override @Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("can override: false"); pw.println("can override: false");
Map<Integer, Flag<?>> knownFlags = Flags.collectFlags(); Map<String, Flag<?>> knownFlags = FlagsFactory.INSTANCE.getKnownFlags();
for (Map.Entry<Integer, Flag<?>> idToFlag : knownFlags.entrySet()) { for (Map.Entry<String, Flag<?>> nameToFlag : knownFlags.entrySet()) {
int id = idToFlag.getKey(); Flag<?> flag = nameToFlag.getValue();
Flag<?> flag = idToFlag.getValue(); int id = flag.getId();
boolean def = false; boolean def = false;
if (mBooleanCache.indexOfKey(flag.getId()) < 0) { if (mBooleanCache.indexOfKey(flag.getId()) < 0) {
if (flag instanceof SysPropBooleanFlag) { if (flag instanceof SysPropBooleanFlag) {

View File

@@ -229,7 +229,7 @@ public class FlagCommand implements Command {
} }
private int flagNameToId(String flagName) { private int flagNameToId(String flagName) {
Map<String, Flag<?>> flagFields = Flags.getFlagFields(); Map<String, Flag<?>> flagFields = FlagsFactory.INSTANCE.getKnownFlags();
for (String fieldName : flagFields.keySet()) { for (String fieldName : flagFields.keySet()) {
if (flagName.equals(fieldName)) { if (flagName.equals(fieldName)) {
return flagFields.get(fieldName).getId(); return flagFields.get(fieldName).getId();
@@ -240,7 +240,7 @@ public class FlagCommand implements Command {
} }
private void printKnownFlags(PrintWriter pw) { private void printKnownFlags(PrintWriter pw) {
Map<String, Flag<?>> fields = Flags.getFlagFields(); Map<String, Flag<?>> fields = FlagsFactory.INSTANCE.getKnownFlags();
int longestFieldName = 0; int longestFieldName = 0;
for (String fieldName : fields.keySet()) { for (String fieldName : fields.keySet()) {

View File

@@ -17,12 +17,11 @@ package com.android.systemui.flags
import android.provider.DeviceConfig import android.provider.DeviceConfig
import com.android.internal.annotations.Keep import com.android.internal.annotations.Keep
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R import com.android.systemui.R
import kotlin.reflect.KClass import com.android.systemui.flags.FlagsFactory.releasedFlag
import kotlin.reflect.full.declaredMembers import com.android.systemui.flags.FlagsFactory.resourceBooleanFlag
import kotlin.reflect.full.isSubclassOf import com.android.systemui.flags.FlagsFactory.sysPropBooleanFlag
import kotlin.reflect.full.staticProperties import com.android.systemui.flags.FlagsFactory.unreleasedFlag
/** /**
* List of [Flag] objects for use in SystemUI. * 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. * See [FeatureFlagsDebug] for instructions on flipping the flags via adb.
*/ */
object Flags { object Flags {
@JvmField val TEAMFOOD = UnreleasedFlag(1) @JvmField val TEAMFOOD = unreleasedFlag(1, "teamfood")
// 100 - notification // 100 - notification
// TODO(b/254512751): Tracking Bug // 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 // 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 // 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 // TODO(b/254512624): Tracking Bug
@JvmField @JvmField
val NOTIFICATION_DRAG_TO_CONTENTS = 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 // 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 // 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 // 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 // TODO(b/254512731): Tracking Bug
@JvmField val NOTIFICATION_DISMISSAL_FADE = UnreleasedFlag(113, teamfood = true) @JvmField
val STABILITY_INDEX_FIX = UnreleasedFlag(114, teamfood = true) val NOTIFICATION_DISMISSAL_FADE =
val SEMI_STABLE_SORT = UnreleasedFlag(115, teamfood = true) 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 // TODO(b/257506350): Tracking Bug
val FSI_CHROME = UnreleasedFlag(117) val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
// next id: 118 // next id: 118
@@ -80,25 +89,27 @@ object Flags {
// public static final BooleanFlag KEYGUARD_LAYOUT = // public static final BooleanFlag KEYGUARD_LAYOUT =
// new BooleanFlag(200, true); // new BooleanFlag(200, true);
// TODO(b/254512713): Tracking Bug // TODO(b/254512713): Tracking Bug
@JvmField val LOCKSCREEN_ANIMATIONS = ReleasedFlag(201) @JvmField val LOCKSCREEN_ANIMATIONS = releasedFlag(201, "lockscreen_animations")
// TODO(b/254512750): Tracking Bug // TODO(b/254512750): Tracking Bug
val NEW_UNLOCK_SWIPE_ANIMATION = ReleasedFlag(202) val NEW_UNLOCK_SWIPE_ANIMATION = releasedFlag(202, "new_unlock_swipe_animation")
val CHARGING_RIPPLE = ResourceBooleanFlag(203, R.bool.flag_charging_ripple) val CHARGING_RIPPLE = resourceBooleanFlag(203, R.bool.flag_charging_ripple, "charging_ripple")
// TODO(b/254512281): Tracking Bug // TODO(b/254512281): Tracking Bug
@JvmField @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 // 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 * Flag to enable the usage of the new bouncer data source. This is a refactor of and eventual
* replacement of KeyguardBouncer.java. * replacement of KeyguardBouncer.java.
*/ */
// TODO(b/254512385): Tracking Bug // 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`. * Whether the user interactor and repository should use `UserSwitcherController`.
@@ -107,7 +118,8 @@ object Flags {
* framework APIs. * framework APIs.
*/ */
// TODO(b/254513286): Tracking Bug // 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. * Whether `UserSwitcherController` should use the user interactor.
@@ -119,24 +131,24 @@ object Flags {
* would created a cycle between controller -> interactor -> controller. * would created a cycle between controller -> interactor -> controller.
*/ */
// TODO(b/254513102): Tracking Bug // 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 * Whether the clock on a wide lock screen should use the new "stepping" animation for moving
* the digits when the clock moves. * 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 * Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository
* will occur in stages. This is one stage of many to come. * will occur in stages. This is one stage of many to come.
*/ */
// TODO(b/255607168): Tracking Bug // 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. * 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 * Note that this flag does not enable individual implementations of quick affordances like the
* new camera quick affordance. Look for individual flags for those. * 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 // 300 - power menu
// TODO(b/254512600): Tracking Bug // TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = ReleasedFlag(300) @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
// 400 - smartspace // 400 - smartspace
// TODO(b/254513100): Tracking Bug // TODO(b/254513100): Tracking Bug
val SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED = ReleasedFlag(401) val SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
val SMARTSPACE = ResourceBooleanFlag(402, R.bool.flag_smartspace) releasedFlag(401, "smartspace_shared_element_transition_enabled")
val SMARTSPACE = resourceBooleanFlag(402, R.bool.flag_smartspace, "smartspace")
// 500 - quick settings // 500 - quick settings
// TODO(b/254512321): Tracking Bug // TODO(b/254512321): Tracking Bug
@JvmField val COMBINED_QS_HEADERS = ReleasedFlag(501) @JvmField val COMBINED_QS_HEADERS = releasedFlag(501, "combined_qs_headers")
val PEOPLE_TILE = ResourceBooleanFlag(502, R.bool.flag_conversations) val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@JvmField @JvmField
val QS_USER_DETAIL_SHORTCUT = 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 // TODO(b/254512747): Tracking Bug
val NEW_HEADER = ReleasedFlag(505) val NEW_HEADER = releasedFlag(505, "new_header")
// TODO(b/254512383): Tracking Bug // TODO(b/254512383): Tracking Bug
@JvmField @JvmField
val FULL_SCREEN_USER_SWITCHER = 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 // 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 // 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 // 600- status bar
// TODO(b/254513246): Tracking Bug // 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 // TODO(b/254512623): Tracking Bug
@Deprecated("Replaced by mobile and wifi specific flags.") @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 // TODO(b/254512660): Tracking Bug
@Deprecated("Replaced by mobile and wifi specific flags.") @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 // 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 // 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 // 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 // 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 // 700 - dialer/calls
// TODO(b/254512734): Tracking Bug // 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 // 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 // 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 // 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 // 801 - region sampling
// TODO(b/254512848): Tracking Bug // TODO(b/254512848): Tracking Bug
val REGION_SAMPLING = UnreleasedFlag(801) val REGION_SAMPLING = unreleasedFlag(801, "region_sampling")
// 802 - wallpaper rendering // 802 - wallpaper rendering
// TODO(b/254512923): Tracking Bug // 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 // 803 - screen contents translation
// TODO(b/254513187): Tracking Bug // TODO(b/254513187): Tracking Bug
val SCREEN_CONTENTS_TRANSLATION = UnreleasedFlag(803) val SCREEN_CONTENTS_TRANSLATION = unreleasedFlag(803, "screen_contents_translation")
// 804 - monochromatic themes // 804 - monochromatic themes
@JvmField @JvmField
val MONOCHROMATIC_THEMES = SysPropBooleanFlag(804, "persist.sysui.monochromatic", false) val MONOCHROMATIC_THEMES =
sysPropBooleanFlag(804, "persist.sysui.monochromatic", default = false)
// 900 - media // 900 - media
// TODO(b/254512697): Tracking Bug // 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 // 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 // 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 // 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 // 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 // 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 // TODO(b/254513168): Tracking Bug
@JvmField val UMO_SURFACE_RIPPLE = UnreleasedFlag(907) @JvmField val UMO_SURFACE_RIPPLE = unreleasedFlag(907, "umo_surface_ripple")
// 1000 - dock // 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 // TODO(b/254512758): Tracking Bug
@JvmField val ROUNDED_BOX_RIPPLE = ReleasedFlag(1002) @JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
// 1100 - windowing // 1100 - windowing
@Keep @Keep
@JvmField @JvmField
val WM_ENABLE_SHELL_TRANSITIONS = 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 // TODO(b/254513207): Tracking Bug
@Keep @Keep
@JvmField @JvmField
val WM_ENABLE_PARTIAL_SCREEN_SHARING = val WM_ENABLE_PARTIAL_SCREEN_SHARING =
UnreleasedFlag( unreleasedFlag(
1102, 1102,
name = "record_task_content", name = "record_task_content",
namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER, namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER,
@@ -281,135 +311,101 @@ object Flags {
// TODO(b/254512674): Tracking Bug // TODO(b/254512674): Tracking Bug
@Keep @Keep
@JvmField @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 @Keep
@JvmField @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 @Keep
@JvmField @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 @Keep
@JvmField @JvmField
val ENABLE_FLING_TO_DISMISS_BUBBLE = 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 @Keep
@JvmField @JvmField
val ENABLE_FLING_TO_DISMISS_PIP = 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 @Keep
@JvmField @JvmField
val ENABLE_PIP_KEEP_CLEAR_ALGORITHM = 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 // 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 // 1200 - predictive back
@Keep @Keep
@JvmField @JvmField
val WM_ENABLE_PREDICTIVE_BACK = val WM_ENABLE_PREDICTIVE_BACK =
SysPropBooleanFlag(1200, "persist.wm.debug.predictive_back", true) sysPropBooleanFlag(1200, "persist.wm.debug.predictive_back", default = true)
@Keep @Keep
@JvmField @JvmField
val WM_ENABLE_PREDICTIVE_BACK_ANIM = 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 @Keep
@JvmField @JvmField
val WM_ALWAYS_ENFORCE_PREDICTIVE_BACK = 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 // 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 // 1300 - screenshots
// TODO(b/254512719): Tracking Bug // 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 // 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 // 1400 - columbus
// TODO(b/254512756): Tracking Bug // 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 // 1500 - chooser
// TODO(b/254512507): Tracking Bug // TODO(b/254512507): Tracking Bug
val CHOOSER_UNBUNDLED = UnreleasedFlag(1500, teamfood = true) val CHOOSER_UNBUNDLED = unreleasedFlag(1500, "chooser_unbundled", teamfood = true)
// 1600 - accessibility // 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 // 1700 - clipboard
@JvmField val CLIPBOARD_OVERLAY_REFACTOR = UnreleasedFlag(1700, teamfood = true) @JvmField
@JvmField val CLIPBOARD_REMOTE_BEHAVIOR = UnreleasedFlag(1701) val CLIPBOARD_OVERLAY_REFACTOR =
unreleasedFlag(1700, "clipboard_overlay_refactor", teamfood = true)
@JvmField val CLIPBOARD_REMOTE_BEHAVIOR = unreleasedFlag(1701, "clipboard_remote_behavior")
// 1800 - shade container // 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 // 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 // 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 // 2100 - Falsing Manager
@JvmField val FALSING_FOR_LONG_TAPS = ReleasedFlag(2100) @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps")
// 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()
}
// | |
// \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
} }

View File

@@ -30,7 +30,7 @@ interface FlagsCommonModule {
@Provides @Provides
@Named(ALL_FLAGS) @Named(ALL_FLAGS)
fun providesAllFlags(): Map<Int, Flag<*>> { fun providesAllFlags(): Map<Int, Flag<*>> {
return Flags.collectFlags() return FlagsFactory.knownFlags.map { it.value.id to it.value }.toMap()
} }
@JvmStatic @JvmStatic

View File

@@ -20,7 +20,6 @@ import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import java.lang.IllegalStateException
import org.junit.Assert.fail import org.junit.Assert.fail
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -29,12 +28,12 @@ import org.junit.runner.RunWith
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
class FakeFeatureFlagsTest : SysuiTestCase() { class FakeFeatureFlagsTest : SysuiTestCase() {
private val unreleasedFlag = UnreleasedFlag(-1000) private val unreleasedFlag = UnreleasedFlag(-1000, "-1000", "test")
private val releasedFlag = ReleasedFlag(-1001) private val releasedFlag = ReleasedFlag(-1001, "-1001", "test")
private val stringFlag = StringFlag(-1002) private val stringFlag = StringFlag(-1002, "-1002", "test")
private val resourceBooleanFlag = ResourceBooleanFlag(-1003, resourceId = -1) private val resourceBooleanFlag = ResourceBooleanFlag(-1003, "-1003", "test", resourceId = -1)
private val resourceStringFlag = ResourceStringFlag(-1004, resourceId = -1) private val resourceStringFlag = ResourceStringFlag(-1004, "-1004", "test", resourceId = -1)
private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, name = "test") private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, "test", "test")
/** /**
* FakeFeatureFlags does not honor any default values. All flags which are accessed must be * 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() assertThat(flags.isEnabled(Flags.TEAMFOOD)).isFalse()
fail("Expected an exception when accessing an unspecified flag.") fail("Expected an exception when accessing an unspecified flag.")
} catch (ex: IllegalStateException) { } catch (ex: IllegalStateException) {
assertThat(ex.message).contains("TEAMFOOD") assertThat(ex.message).contains("id=1")
} }
try { try {
assertThat(flags.isEnabled(unreleasedFlag)).isFalse() assertThat(flags.isEnabled(unreleasedFlag)).isFalse()

View File

@@ -57,21 +57,32 @@ import org.mockito.Mockito.`when` as whenever
class FeatureFlagsDebugTest : SysuiTestCase() { class FeatureFlagsDebugTest : SysuiTestCase() {
private lateinit var mFeatureFlagsDebug: FeatureFlagsDebug private lateinit var mFeatureFlagsDebug: FeatureFlagsDebug
@Mock private lateinit var flagManager: FlagManager @Mock
@Mock private lateinit var mockContext: Context private lateinit var flagManager: FlagManager
@Mock private lateinit var secureSettings: SecureSettings @Mock
@Mock private lateinit var systemProperties: SystemPropertiesHelper private lateinit var mockContext: Context
@Mock private lateinit var resources: Resources @Mock
@Mock private lateinit var commandRegistry: CommandRegistry private lateinit var secureSettings: SecureSettings
@Mock private lateinit var restarter: Restarter @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 val flagMap = mutableMapOf<Int, Flag<*>>()
private lateinit var broadcastReceiver: BroadcastReceiver private lateinit var broadcastReceiver: BroadcastReceiver
private lateinit var clearCacheAction: Consumer<Int> private lateinit var clearCacheAction: Consumer<Int>
private val serverFlagReader = ServerFlagReaderFake() private val serverFlagReader = ServerFlagReaderFake()
private val deviceConfig = DeviceConfigProxyFake() private val deviceConfig = DeviceConfigProxyFake()
private val teamfoodableFlagA = UnreleasedFlag(500, teamfood = true) private val teamfoodableFlagA = UnreleasedFlag(
private val teamfoodableFlagB = ReleasedFlag(501, teamfood = true) 500, name = "a", namespace = "test", teamfood = true
)
private val teamfoodableFlagB = ReleasedFlag(
501, name = "b", namespace = "test", teamfood = true
)
@Before @Before
fun setup() { fun setup() {
@@ -91,8 +102,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
mFeatureFlagsDebug.init() mFeatureFlagsDebug.init()
verify(flagManager).onSettingsChangedAction = any() verify(flagManager).onSettingsChangedAction = any()
broadcastReceiver = withArgCaptor { broadcastReceiver = withArgCaptor {
verify(mockContext).registerReceiver(capture(), any(), nullable(), nullable(), verify(mockContext).registerReceiver(
any()) capture(), any(), nullable(), nullable(),
any()
)
} }
clearCacheAction = withArgCaptor { clearCacheAction = withArgCaptor {
verify(flagManager).clearCacheAction = capture() 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(3), any())).thenReturn(true)
whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false) whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(2))).isTrue() assertThat(
assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(3))).isTrue() mFeatureFlagsDebug.isEnabled(
assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(4))).isFalse() ReleasedFlag(
assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(5))).isFalse() 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 @Test
@@ -137,9 +182,9 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun teamFoodFlag_Overridden() { fun teamFoodFlag_Overridden() {
whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any())) whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
.thenReturn(true) .thenReturn(true)
whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any())) whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
.thenReturn(false) .thenReturn(false)
whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse() 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(3), any())).thenReturn(true)
whenever(flagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false) whenever(flagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(1, 1001))).isFalse() assertThat(
assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(2, 1002))).isTrue() mFeatureFlagsDebug.isEnabled(
assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(3, 1003))).isTrue() 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) { 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. // 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. // This prevents developers from not noticing when they reference an invalid resource.
Assert.assertThrows(NameNotFoundException::class.java) { 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) return@thenAnswer it.getArgument(1)
} }
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(1, "a"))).isFalse() assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(1, "a", "test"))).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(2, "b"))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(2, "b", "test"))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(3, "c", true))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(3, "c", "test", true))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(4, "d", false))).isFalse() assertThat(
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(5, "e"))).isFalse() mFeatureFlagsDebug.isEnabled(
SysPropBooleanFlag(
4,
"d",
"test",
false
)
)
).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(SysPropBooleanFlag(5, "e", "test"))).isFalse()
} }
@Test @Test
fun readStringFlag() { fun readStringFlag() {
whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo") whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar") whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz") assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "1", "test", "biz"))).isEqualTo("biz")
assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "baz"))).isEqualTo("baz") assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "2", "test", "baz"))).isEqualTo("baz")
assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "buz"))).isEqualTo("foo") assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "3", "test", "buz"))).isEqualTo("foo")
assertThat(mFeatureFlagsDebug.getString(StringFlag(4, "buz"))).isEqualTo("bar") assertThat(mFeatureFlagsDebug.getString(StringFlag(4, "4", "test", "buz"))).isEqualTo("bar")
} }
@Test @Test
@@ -213,20 +276,47 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4") whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4")
whenever(flagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6") whenever(flagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6")
assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(1, 1001))).isEqualTo("") assertThat(
assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(2, 1002))).isEqualTo("resource2") mFeatureFlagsDebug.getString(
assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(3, 1003))).isEqualTo("override3") 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) { Assert.assertThrows(NullPointerException::class.java) {
mFeatureFlagsDebug.getString(ResourceStringFlag(4, 1004)) mFeatureFlagsDebug.getString(ResourceStringFlag(4, "4", "test", 1004))
} }
Assert.assertThrows(NameNotFoundException::class.java) { 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. // 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. // This prevents developers from not noticing when they reference an invalid resource.
Assert.assertThrows(NameNotFoundException::class.java) { 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() { fun readIntFlag() {
whenever(flagManager.readFlagValue<Int>(eq(3), any())).thenReturn(22) whenever(flagManager.readFlagValue<Int>(eq(3), any())).thenReturn(22)
whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(48) whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(48)
assertThat(mFeatureFlagsDebug.getInt(IntFlag(1, 12))).isEqualTo(12) assertThat(mFeatureFlagsDebug.getInt(IntFlag(1, "1", "test", 12))).isEqualTo(12)
assertThat(mFeatureFlagsDebug.getInt(IntFlag(2, 93))).isEqualTo(93) assertThat(mFeatureFlagsDebug.getInt(IntFlag(2, "2", "test", 93))).isEqualTo(93)
assertThat(mFeatureFlagsDebug.getInt(IntFlag(3, 8))).isEqualTo(22) assertThat(mFeatureFlagsDebug.getInt(IntFlag(3, "3", "test", 8))).isEqualTo(22)
assertThat(mFeatureFlagsDebug.getInt(IntFlag(4, 234))).isEqualTo(48) assertThat(mFeatureFlagsDebug.getInt(IntFlag(4, "4", "test", 234))).isEqualTo(48)
} }
@Test @Test
@@ -253,26 +343,26 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(500) whenever(flagManager.readFlagValue<Int>(eq(4), any())).thenReturn(500)
whenever(flagManager.readFlagValue<Int>(eq(5), any())).thenReturn(9519) whenever(flagManager.readFlagValue<Int>(eq(5), any())).thenReturn(9519)
assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(1, 1001))).isEqualTo(88) assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(1, "1", "test", 1001))).isEqualTo(88)
assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(2, 1002))).isEqualTo(61) assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(2, "2", "test", 1002))).isEqualTo(61)
assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(3, 1003))).isEqualTo(20) assertThat(mFeatureFlagsDebug.getInt(ResourceIntFlag(3, "3", "test", 1003))).isEqualTo(20)
Assert.assertThrows(NotFoundException::class.java) { 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. // 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. // This prevents developers from not noticing when they reference an invalid resource.
Assert.assertThrows(NotFoundException::class.java) { Assert.assertThrows(NotFoundException::class.java) {
mFeatureFlagsDebug.getInt(ResourceIntFlag(5, 1005)) mFeatureFlagsDebug.getInt(ResourceIntFlag(5, "5", "test", 1005))
} }
} }
@Test @Test
fun broadcastReceiver_IgnoresInvalidData() { fun broadcastReceiver_IgnoresInvalidData() {
addFlag(UnreleasedFlag(1)) addFlag(UnreleasedFlag(1, "1", "test"))
addFlag(ResourceBooleanFlag(2, 1002)) addFlag(ResourceBooleanFlag(2, "2", "test", 1002))
addFlag(StringFlag(3, "flag3")) addFlag(StringFlag(3, "3", "test", "flag3"))
addFlag(ResourceStringFlag(4, 1004)) addFlag(ResourceStringFlag(4, "4", "test", 1004))
broadcastReceiver.onReceive(mockContext, null) broadcastReceiver.onReceive(mockContext, null)
broadcastReceiver.onReceive(mockContext, Intent()) broadcastReceiver.onReceive(mockContext, Intent())
@@ -288,7 +378,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun intentWithId_NoValueKeyClears() { fun intentWithId_NoValueKeyClears() {
addFlag(UnreleasedFlag(1)) addFlag(UnreleasedFlag(1, name = "1", namespace = "test"))
// trying to erase an id not in the map does nothing // trying to erase an id not in the map does nothing
broadcastReceiver.onReceive( broadcastReceiver.onReceive(
@@ -307,10 +397,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun setBooleanFlag() { fun setBooleanFlag() {
addFlag(UnreleasedFlag(1)) addFlag(UnreleasedFlag(1, "1", "test"))
addFlag(UnreleasedFlag(2)) addFlag(UnreleasedFlag(2, "2", "test"))
addFlag(ResourceBooleanFlag(3, 1003)) addFlag(ResourceBooleanFlag(3, "3", "test", 1003))
addFlag(ResourceBooleanFlag(4, 1004)) addFlag(ResourceBooleanFlag(4, "4", "test", 1004))
setByBroadcast(1, false) setByBroadcast(1, false)
verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}") verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}")
@@ -327,8 +417,8 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun setStringFlag() { fun setStringFlag() {
addFlag(StringFlag(1, "flag1")) addFlag(StringFlag(1, "flag1", "1", "test"))
addFlag(ResourceStringFlag(2, 1002)) addFlag(ResourceStringFlag(2, "2", "test", 1002))
setByBroadcast(1, "override1") setByBroadcast(1, "override1")
verifyPutData(1, "{\"type\":\"string\",\"value\":\"override1\"}") verifyPutData(1, "{\"type\":\"string\",\"value\":\"override1\"}")
@@ -339,7 +429,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun setFlag_ClearsCache() { 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") whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original")
// gets the flag & cache it // gets the flag & cache it
@@ -361,7 +451,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun serverSide_Overrides_MakesFalse() { fun serverSide_Overrides_MakesFalse() {
val flag = ReleasedFlag(100) val flag = ReleasedFlag(100, "100", "test")
serverFlagReader.setFlagValue(flag.namespace, flag.name, false) serverFlagReader.setFlagValue(flag.namespace, flag.name, false)
@@ -370,7 +460,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun serverSide_Overrides_MakesTrue() { fun serverSide_Overrides_MakesTrue() {
val flag = UnreleasedFlag(100) val flag = UnreleasedFlag(100, name = "100", namespace = "test")
serverFlagReader.setFlagValue(flag.namespace, flag.name, true) serverFlagReader.setFlagValue(flag.namespace, flag.name, true)
@@ -379,13 +469,13 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test @Test
fun dumpFormat() { fun dumpFormat() {
val flag1 = ReleasedFlag(1) val flag1 = ReleasedFlag(1, "1", "test")
val flag2 = ResourceBooleanFlag(2, 1002) val flag2 = ResourceBooleanFlag(2, "2", "test", 1002)
val flag3 = UnreleasedFlag(3) val flag3 = UnreleasedFlag(3, "3", "test")
val flag4 = StringFlag(4, "") val flag4 = StringFlag(4, "4", "test", "")
val flag5 = StringFlag(5, "flag5default") val flag5 = StringFlag(5, "5", "test", "flag5default")
val flag6 = ResourceStringFlag(6, 1006) val flag6 = ResourceStringFlag(6, "6", "test", 1006)
val flag7 = ResourceStringFlag(7, 1007) val flag7 = ResourceStringFlag(7, "7", "test", 1007)
whenever(resources.getBoolean(1002)).thenReturn(true) whenever(resources.getBoolean(1002)).thenReturn(true)
whenever(resources.getString(1006)).thenReturn("resource1006") whenever(resources.getString(1006)).thenReturn("resource1006")

View File

@@ -59,7 +59,9 @@ class FeatureFlagsReleaseTest : SysuiTestCase() {
fun testBooleanResourceFlag() { fun testBooleanResourceFlag() {
val flagId = 213 val flagId = 213
val flagResourceId = 3 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) whenever(mResources.getBoolean(flagResourceId)).thenReturn(true)
assertThat(mFeatureFlagsRelease.isEnabled(flag)).isTrue() assertThat(mFeatureFlagsRelease.isEnabled(flag)).isTrue()
} }
@@ -71,14 +73,16 @@ class FeatureFlagsReleaseTest : SysuiTestCase() {
whenever(mResources.getString(1003)).thenReturn(null) whenever(mResources.getString(1003)).thenReturn(null)
whenever(mResources.getString(1004)).thenAnswer { throw NameNotFoundException() } whenever(mResources.getString(1004)).thenAnswer { throw NameNotFoundException() }
assertThat(mFeatureFlagsRelease.getString(ResourceStringFlag(1, 1001))).isEqualTo("") assertThat(mFeatureFlagsRelease.getString(
assertThat(mFeatureFlagsRelease.getString(ResourceStringFlag(2, 1002))).isEqualTo("res2") ResourceStringFlag(1, "1", "test", 1001))).isEqualTo("")
assertThat(mFeatureFlagsRelease.getString(
ResourceStringFlag(2, "2", "test", 1002))).isEqualTo("res2")
assertThrows(NullPointerException::class.java) { assertThrows(NullPointerException::class.java) {
mFeatureFlagsRelease.getString(ResourceStringFlag(3, 1003)) mFeatureFlagsRelease.getString(ResourceStringFlag(3, "3", "test", 1003))
} }
assertThrows(NameNotFoundException::class.java) { 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() { fun testSysPropBooleanFlag() {
val flagId = 213 val flagId = 213
val flagName = "sys_prop_flag" val flagName = "sys_prop_flag"
val flagNamespace = "test"
val flagDefault = true val flagDefault = true
val flag = SysPropBooleanFlag(flagId, flagName, flagDefault) val flag = SysPropBooleanFlag(flagId, flagName, flagNamespace, flagDefault)
whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault) whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault)
assertThat(mFeatureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault) assertThat(mFeatureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault)
} }
@Test @Test
fun serverSide_OverridesReleased_MakesFalse() { fun serverSide_OverridesReleased_MakesFalse() {
val flag = ReleasedFlag(100) val flag = ReleasedFlag(100, "100", "test")
serverFlagReader.setFlagValue(flag.namespace, flag.name, false) serverFlagReader.setFlagValue(flag.namespace, flag.name, false)
@@ -104,7 +109,7 @@ class FeatureFlagsReleaseTest : SysuiTestCase() {
@Test @Test
fun serverSide_OverridesUnreleased_Ignored() { fun serverSide_OverridesUnreleased_Ignored() {
val flag = UnreleasedFlag(100) val flag = UnreleasedFlag(100, "100", "test")
serverFlagReader.setFlagValue(flag.namespace, flag.name, true) serverFlagReader.setFlagValue(flag.namespace, flag.name, true)

View File

@@ -33,10 +33,10 @@ class FlagCommandTest : SysuiTestCase() {
@Mock private lateinit var featureFlags: FeatureFlagsDebug @Mock private lateinit var featureFlags: FeatureFlagsDebug
@Mock private lateinit var pw: PrintWriter @Mock private lateinit var pw: PrintWriter
private val flagMap = mutableMapOf<Int, Flag<*>>() private val flagMap = mutableMapOf<Int, Flag<*>>()
private val flagA = UnreleasedFlag(500) private val flagA = UnreleasedFlag(500, "500", "test")
private val flagB = ReleasedFlag(501) private val flagB = ReleasedFlag(501, "501", "test")
private val stringFlag = StringFlag(502, "abracadabra") private val stringFlag = StringFlag(502, "502", "test", "abracadabra")
private val intFlag = IntFlag(503, 12) private val intFlag = IntFlag(503, "503", "test", 12)
private lateinit var cmd: FlagCommand private lateinit var cmd: FlagCommand

View File

@@ -64,14 +64,14 @@ class FlagManagerTest : SysuiTestCase() {
verifyNoMoreInteractions(mFlagSettingsHelper) verifyNoMoreInteractions(mFlagSettingsHelper)
// adding the first listener registers the observer // adding the first listener registers the observer
mFlagManager.addListener(ReleasedFlag(1), listener1) mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1)
val observer = withArgCaptor<ContentObserver> { val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
} }
verifyNoMoreInteractions(mFlagSettingsHelper) verifyNoMoreInteractions(mFlagSettingsHelper)
// adding another listener does nothing // adding another listener does nothing
mFlagManager.addListener(ReleasedFlag(2), listener2) mFlagManager.addListener(ReleasedFlag(2, "2", "test"), listener2)
verifyNoMoreInteractions(mFlagSettingsHelper) verifyNoMoreInteractions(mFlagSettingsHelper)
// removing the original listener does nothing with second one still present // removing the original listener does nothing with second one still present
@@ -89,7 +89,7 @@ class FlagManagerTest : SysuiTestCase() {
val listener = mock<FlagListenable.Listener>() val listener = mock<FlagListenable.Listener>()
val clearCacheAction = mock<Consumer<Int>>() val clearCacheAction = mock<Consumer<Int>>()
mFlagManager.clearCacheAction = clearCacheAction mFlagManager.clearCacheAction = clearCacheAction
mFlagManager.addListener(ReleasedFlag(1), listener) mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener)
val observer = withArgCaptor<ContentObserver> { val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
} }
@@ -101,8 +101,8 @@ class FlagManagerTest : SysuiTestCase() {
fun testObserverInvokesListeners() { fun testObserverInvokesListeners() {
val listener1 = mock<FlagListenable.Listener>() val listener1 = mock<FlagListenable.Listener>()
val listener10 = mock<FlagListenable.Listener>() val listener10 = mock<FlagListenable.Listener>()
mFlagManager.addListener(ReleasedFlag(1), listener1) mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1)
mFlagManager.addListener(ReleasedFlag(10), listener10) mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener10)
val observer = withArgCaptor<ContentObserver> { val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture()) verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
} }
@@ -127,8 +127,8 @@ class FlagManagerTest : SysuiTestCase() {
fun testOnlySpecificFlagListenerIsInvoked() { fun testOnlySpecificFlagListenerIsInvoked() {
val listener1 = mock<FlagListenable.Listener>() val listener1 = mock<FlagListenable.Listener>()
val listener10 = mock<FlagListenable.Listener>() val listener10 = mock<FlagListenable.Listener>()
mFlagManager.addListener(ReleasedFlag(1), listener1) mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener1)
mFlagManager.addListener(ReleasedFlag(10), listener10) mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener10)
mFlagManager.dispatchListenersAndMaybeRestart(1, null) mFlagManager.dispatchListenersAndMaybeRestart(1, null)
val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> { val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -148,8 +148,8 @@ class FlagManagerTest : SysuiTestCase() {
@Test @Test
fun testSameListenerCanBeUsedForMultipleFlags() { fun testSameListenerCanBeUsedForMultipleFlags() {
val listener = mock<FlagListenable.Listener>() val listener = mock<FlagListenable.Listener>()
mFlagManager.addListener(ReleasedFlag(1), listener) mFlagManager.addListener(ReleasedFlag(1, "1", "test"), listener)
mFlagManager.addListener(ReleasedFlag(10), listener) mFlagManager.addListener(ReleasedFlag(10, "10", "test"), listener)
mFlagManager.dispatchListenersAndMaybeRestart(1, null) mFlagManager.dispatchListenersAndMaybeRestart(1, null)
val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> { val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -177,7 +177,7 @@ class FlagManagerTest : SysuiTestCase() {
@Test @Test
fun testListenerCanSuppressRestart() { fun testListenerCanSuppressRestart() {
val restartAction = mock<Consumer<Boolean>>() val restartAction = mock<Consumer<Boolean>>()
mFlagManager.addListener(ReleasedFlag(1)) { event -> mFlagManager.addListener(ReleasedFlag(1, "1", "test")) { event ->
event.requestNoRestart() event.requestNoRestart()
} }
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -188,7 +188,7 @@ class FlagManagerTest : SysuiTestCase() {
@Test @Test
fun testListenerOnlySuppressesRestartForOwnFlag() { fun testListenerOnlySuppressesRestartForOwnFlag() {
val restartAction = mock<Consumer<Boolean>>() val restartAction = mock<Consumer<Boolean>>()
mFlagManager.addListener(ReleasedFlag(10)) { event -> mFlagManager.addListener(ReleasedFlag(10, "10", "test")) { event ->
event.requestNoRestart() event.requestNoRestart()
} }
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -199,10 +199,10 @@ class FlagManagerTest : SysuiTestCase() {
@Test @Test
fun testRestartWhenNotAllListenersRequestSuppress() { fun testRestartWhenNotAllListenersRequestSuppress() {
val restartAction = mock<Consumer<Boolean>>() val restartAction = mock<Consumer<Boolean>>()
mFlagManager.addListener(ReleasedFlag(10)) { event -> mFlagManager.addListener(ReleasedFlag(10, "10", "test")) { event ->
event.requestNoRestart() event.requestNoRestart()
} }
mFlagManager.addListener(ReleasedFlag(10)) { mFlagManager.addListener(ReleasedFlag(10, "10", "test")) {
// do not request // do not request
} }
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction) mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)

View File

@@ -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)
}
}

View File

@@ -50,7 +50,7 @@ class ServerFlagReaderImplTest : SysuiTestCase() {
@Test @Test
fun testChange_alertsListener() { fun testChange_alertsListener() {
val flag = ReleasedFlag(1) val flag = ReleasedFlag(1, "1", "test")
serverFlagReader.listenForChanges(listOf(flag), changeListener) serverFlagReader.listenForChanges(listOf(flag), changeListener)
deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false) deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false)

View File

@@ -27,7 +27,7 @@ class FakeFeatureFlags : FeatureFlags {
private val listenerFlagIds = mutableMapOf<FlagListenable.Listener, MutableSet<Int>>() private val listenerFlagIds = mutableMapOf<FlagListenable.Listener, MutableSet<Int>>()
init { init {
Flags.flagFields.forEach { entry: Map.Entry<String, Flag<*>> -> FlagsFactory.knownFlags.forEach { entry: Map.Entry<String, Flag<*>> ->
knownFlagNames[entry.value.id] = entry.key knownFlagNames[entry.value.id] = entry.key
} }
} }