Implement new feature flag strategy for AEC selection.

This commit is contained in:
Greyson Parrelli
2022-02-22 13:45:02 -05:00
committed by Alex Hart
parent d935d1deca
commit 3ac63cc59d
3 changed files with 103 additions and 23 deletions

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.service.webrtc
import android.os.Build
import androidx.annotation.VisibleForTesting
import org.signal.ringrtc.CallManager.AudioProcessingMethod
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.FeatureFlags
@@ -10,24 +11,47 @@ import org.thoughtcrime.securesms.util.FeatureFlags
*/
object AudioProcessingMethodSelector {
private val hardwareModels: Set<String> by lazy {
FeatureFlags.hardwareAecModels()
.split(",")
.map { it.trim() }
.filter { it.isNotEmpty() }
.toSet()
}
@JvmStatic
fun get(): AudioProcessingMethod {
if (SignalStore.internalValues().audioProcessingMethod() != AudioProcessingMethod.Default) {
return SignalStore.internalValues().audioProcessingMethod()
}
val useAec3: Boolean = FeatureFlags.useAec3()
return when {
FeatureFlags.forceDefaultAec() -> AudioProcessingMethod.Default
hardwareModels.contains(Build.MODEL) -> AudioProcessingMethod.ForceHardware
else -> AudioProcessingMethod.ForceSoftwareAecM
isHardwareBlocklisted() && useAec3 -> AudioProcessingMethod.ForceSoftwareAec3
isHardwareBlocklisted() -> AudioProcessingMethod.ForceSoftwareAecM
isSoftwareBlocklisted() -> AudioProcessingMethod.ForceHardware
Build.VERSION.SDK_INT < 29 && FeatureFlags.useHardwareAecIfOlderThanApi29() -> AudioProcessingMethod.ForceHardware
Build.VERSION.SDK_INT < 29 && useAec3 -> AudioProcessingMethod.ForceSoftwareAec3
Build.VERSION.SDK_INT < 29 -> AudioProcessingMethod.ForceSoftwareAecM
else -> AudioProcessingMethod.ForceHardware
}
}
private fun isHardwareBlocklisted(): Boolean {
return modelInList(Build.MODEL, FeatureFlags.hardwareAecBlocklistModels())
}
private fun isSoftwareBlocklisted(): Boolean {
return modelInList(Build.MODEL, FeatureFlags.softwareAecBlocklistModels())
}
@VisibleForTesting
fun modelInList(model: String, serializedList: String): Boolean {
val items: List<String> = serializedList
.split(",")
.map { it.trim() }
.filter { it.isNotEmpty() }
.toList()
val exactMatches = items.filter { it.last() != '*' }
val prefixMatches = items.filter { it.last() == '*' }
return exactMatches.contains(model) ||
prefixMatches
.map { it.substring(0, it.length - 1) }
.any { model.startsWith(it) }
}
}

View File

@@ -88,11 +88,13 @@ public final class FeatureFlags {
private static final String DONOR_BADGES = "android.donorBadges.6";
private static final String DONOR_BADGES_DISPLAY = "android.donorBadges.display.4";
private static final String CDSH = "android.cdsh";
private static final String HARDWARE_AEC_MODELS = "android.calling.hardwareAecModels";
private static final String FORCE_DEFAULT_AEC = "android.calling.forceDefaultAec";
private static final String STORIES = "android.stories";
private static final String STORIES_TEXT_FUNCTIONS = "android.stories.text.functions";
private static final String STORIES_TEXT_POSTS = "android.stories.text.posts";
private static final String HARDWARE_AEC_BLOCKLIST_MODELS = "android.calling.hardwareAecBlockList";
private static final String SOFTWARE_AEC_BLOCKLIST_MODELS = "android.calling.softwareAecBlockList";
private static final String USE_HARDWARE_AEC_IF_OLD = "android.calling.useHardwareAecIfOlderThanApi29";
private static final String USE_AEC3 = "android.calling.useAec3";
/**
* We will only store remote values for flags in this set. If you want a flag to be controllable
@@ -133,11 +135,13 @@ public final class FeatureFlags {
SENDER_KEY_MAX_AGE,
DONOR_BADGES,
DONOR_BADGES_DISPLAY,
HARDWARE_AEC_MODELS,
FORCE_DEFAULT_AEC,
STORIES,
STORIES_TEXT_FUNCTIONS,
STORIES_TEXT_POSTS
STORIES_TEXT_POSTS,
HARDWARE_AEC_BLOCKLIST_MODELS,
SOFTWARE_AEC_BLOCKLIST_MODELS,
USE_HARDWARE_AEC_IF_OLD,
USE_AEC3
);
@VisibleForTesting
@@ -192,7 +196,10 @@ public final class FeatureFlags {
SENDER_KEY_MAX_AGE,
DONOR_BADGES_DISPLAY,
DONATE_MEGAPHONE,
FORCE_DEFAULT_AEC
HARDWARE_AEC_BLOCKLIST_MODELS,
SOFTWARE_AEC_BLOCKLIST_MODELS,
USE_HARDWARE_AEC_IF_OLD,
USE_AEC3
);
/**
@@ -454,14 +461,24 @@ public final class FeatureFlags {
return Environment.IS_STAGING && getBoolean(CDSH, false);
}
/** A comma-separated list of models that should use hardware AEC for calling. */
public static @NonNull String hardwareAecModels() {
return getString(HARDWARE_AEC_MODELS, "");
/** A comma-separated list of models that should *not* use hardware AEC for calling. */
public static @NonNull String hardwareAecBlocklistModels() {
return getString(HARDWARE_AEC_BLOCKLIST_MODELS, "");
}
/** Whether or not all devices should be forced into using default AEC for calling. */
public static boolean forceDefaultAec() {
return getBoolean(FORCE_DEFAULT_AEC, false);
/** A comma-separated list of models that should *not* use software AEC for calling. */
public static @NonNull String softwareAecBlocklistModels() {
return getString(SOFTWARE_AEC_BLOCKLIST_MODELS, "");
}
/** Whether or not hardware AEC should be used for calling on devices older than API 29. */
public static boolean useHardwareAecIfOlderThanApi29() {
return getBoolean(USE_HARDWARE_AEC_IF_OLD, false);
}
/** Whether or not {@link org.signal.ringrtc.CallManager.AudioProcessingMethod#ForceSoftwareAec3} can be used */
public static boolean useAec3() {
return getBoolean(USE_AEC3, true);
}
/** Only for rendering debug info. */