From 91d3f331e5c4e253be5deade41befd836e00acb1 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 5 Aug 2022 09:38:04 -0400 Subject: [PATCH] Make CameraX blocklist remote configurable. --- .../camerax/CameraXModelBlacklist.java | 120 ------------------ .../camerax/CameraXModelBlocklist.kt | 17 +++ .../mediasend/camerax/CameraXUtil.java | 2 +- .../webrtc/RingRtcDynamicConfiguration.kt | 27 +--- .../securesms/util/FeatureFlags.java | 12 +- .../org/signal/core/util/StringExtensions.kt | 23 ++++ .../util/StringExtensions_asListContains.kt | 6 +- 7 files changed, 59 insertions(+), 148 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlacklist.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlocklist.kt create mode 100644 core-util/src/main/java/org/signal/core/util/StringExtensions.kt rename app/src/test/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfigurationTest_inList.kt => core-util/src/test/java/org/signal/core/util/StringExtensions_asListContains.kt (83%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlacklist.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlacklist.java deleted file mode 100644 index fe16aa8564..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlacklist.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.thoughtcrime.securesms.mediasend.camerax; - -import android.os.Build; - -import java.util.HashSet; -import java.util.Set; - -public final class CameraXModelBlacklist { - private static final Set BLACKLIST = new HashSet() {{ - // Pixel 4 -// add("Pixel 4"); -// add("Pixel 4 XL"); - - // Huawei Mate 10 - add("ALP-L29"); - add("ALP-L09"); - add("ALP-AL00"); - - // Huawei Mate 10 Pro - add("BLA-L29"); - add("BLA-L09"); - add("BLA-AL00"); - add("BLA-A09"); - - // Huawei Mate 20 - add("HMA-L29"); - add("HMA-L09"); - add("HMA-LX9"); - add("HMA-AL00"); - - // Huawei Mate 20 Pro - add("LYA-L09"); - add("LYA-L29"); - add("LYA-AL00"); - add("LYA-AL10"); - add("LYA-TL00"); - add("LYA-L0C"); - - // Huawei Mate 20 X - add("EVR-L29"); - add("EVR-AL00"); - add("EVR-TL00"); - - // Huawei P20 - add("EML-L29C"); - add("EML-L09C"); - add("EML-AL00"); - add("EML-TL00"); - add("EML-L29"); - add("EML-L09"); - - // Huawei P20 Pro - add("CLT-L29C"); - add("CLT-L29"); - add("CLT-L09C"); - add("CLT-L09"); - add("CLT-AL00"); - add("CLT-AL01"); - add("CLT-TL01"); - add("CLT-AL00L"); - add("CLT-L04"); - add("HW-01K"); - - // Huawei P30 - add("ELE-L29"); - add("ELE-L09"); - add("ELE-AL00"); - add("ELE-TL00"); - add("ELE-L04"); - - // Huawei P30 Pro - add("VOG-L29"); - add("VOG-L09"); - add("VOG-AL00"); - add("VOG-TL00"); - add("VOG-L04"); - add("VOG-AL10"); - - // Huawei Honor 10 - add("COL-AL10"); - add("COL-L29"); - add("COL-L19"); - - // Huawei Honor 20 - add("YAL-L21"); - add("YAL-AL00"); - add("YAL-TL00"); - - // Samsung Galaxy S6 - add("SM-G920F"); - - // Honor View 10 - add("BKL-AL20"); - add("BKL-L04"); - add("BKL-L09"); - add("BKL-AL00"); - - // Honor View 20 - add("PCT-AL10"); - add("PCT-TL10"); - add("PCT-L29"); - - // Honor Play - add("COR-L29"); - add("COR-L09"); - add("COR-AL00"); - add("COR-AL10"); - add("COR-TL10"); - - // Motorola G20 - add("moto g(20)"); - }}; - - private CameraXModelBlacklist() { - } - - public static boolean isBlacklisted() { - return BLACKLIST.contains(Build.MODEL); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlocklist.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlocklist.kt new file mode 100644 index 0000000000..cfea065b89 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXModelBlocklist.kt @@ -0,0 +1,17 @@ +package org.thoughtcrime.securesms.mediasend.camerax + +import android.os.Build +import org.signal.core.util.asListContains +import org.thoughtcrime.securesms.util.FeatureFlags + +/** + * Some phones don't work well with CameraX. This class uses a remote config to decide + * which phones should fall back to the legacy camera. + */ +object CameraXModelBlocklist { + + @JvmStatic + fun isBlocklisted(): Boolean { + return FeatureFlags.cameraXModelBlocklist().asListContains(Build.MODEL) + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXUtil.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXUtil.java index 0caf1153d3..2ac1a8c2f2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/camerax/CameraXUtil.java @@ -106,7 +106,7 @@ public class CameraXUtil { } public static boolean isSupported() { - return Build.VERSION.SDK_INT >= 21 && !CameraXModelBlacklist.isBlacklisted(); + return Build.VERSION.SDK_INT >= 21 && !CameraXModelBlocklist.isBlocklisted(); } @RequiresApi(21) diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfiguration.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfiguration.kt index 8ed2bd9e87..96a5666577 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfiguration.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfiguration.kt @@ -1,7 +1,7 @@ package org.thoughtcrime.securesms.service.webrtc import android.os.Build -import androidx.annotation.VisibleForTesting +import org.signal.core.util.asListContains import org.signal.ringrtc.CallManager.AudioProcessingMethod import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.util.FeatureFlags @@ -31,32 +31,15 @@ object RingRtcDynamicConfiguration { } fun isTelecomAllowedForDevice(): Boolean { - return modelInList(Build.MANUFACTURER.lowercase(), FeatureFlags.telecomManufacturerAllowList().lowercase()) && - !modelInList(Build.MODEL.lowercase(), FeatureFlags.telecomModelBlockList().lowercase()) + return FeatureFlags.telecomManufacturerAllowList().lowercase().asListContains(Build.MANUFACTURER.lowercase()) && + !FeatureFlags.telecomModelBlockList().lowercase().asListContains(Build.MODEL.lowercase()) } private fun isHardwareBlocklisted(): Boolean { - return modelInList(Build.MODEL, FeatureFlags.hardwareAecBlocklistModels()) + return FeatureFlags.hardwareAecBlocklistModels().asListContains(Build.MODEL) } private fun isSoftwareBlocklisted(): Boolean { - return modelInList(Build.MODEL, FeatureFlags.softwareAecBlocklistModels()) - } - - @VisibleForTesting - fun modelInList(model: String, serializedList: String): Boolean { - val items: List = 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) } + return FeatureFlags.softwareAecBlocklistModels().asListContains(Build.MODEL) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index a864d5b1b5..6f0a6e410c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -99,6 +99,7 @@ public final class FeatureFlags { private static final String GIFT_BADGE_SEND_SUPPORT = "android.giftBadges.sending.2"; private static final String TELECOM_MANUFACTURER_ALLOWLIST = "android.calling.telecomAllowList"; private static final String TELECOM_MODEL_BLOCKLIST = "android.calling.telecomModelBlockList"; + private static final String CAMERAX_MODEL_BLOCKLIST = "android.cameraXModelBlockList"; /** * We will only store remote values for flags in this set. If you want a flag to be controllable @@ -150,7 +151,8 @@ public final class FeatureFlags { GIFT_BADGE_RECEIVE_SUPPORT, GIFT_BADGE_SEND_SUPPORT, TELECOM_MANUFACTURER_ALLOWLIST, - TELECOM_MODEL_BLOCKLIST + TELECOM_MODEL_BLOCKLIST, + CAMERAX_MODEL_BLOCKLIST ); @VisibleForTesting @@ -211,7 +213,8 @@ public final class FeatureFlags { PAYMENTS_COUNTRY_BLOCKLIST, USE_FCM_FOREGROUND_SERVICE, TELECOM_MANUFACTURER_ALLOWLIST, - TELECOM_MODEL_BLOCKLIST + TELECOM_MODEL_BLOCKLIST, + CAMERAX_MODEL_BLOCKLIST ); /** @@ -492,6 +495,11 @@ public final class FeatureFlags { return getString(TELECOM_MODEL_BLOCKLIST, ""); } + /** A comma-separated list of manufacturers that should *not* use CameraX. */ + public static @NonNull String cameraXModelBlocklist() { + return getString(CAMERAX_MODEL_BLOCKLIST, ""); + } + /** 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); diff --git a/core-util/src/main/java/org/signal/core/util/StringExtensions.kt b/core-util/src/main/java/org/signal/core/util/StringExtensions.kt new file mode 100644 index 0000000000..a7e8befdc9 --- /dev/null +++ b/core-util/src/main/java/org/signal/core/util/StringExtensions.kt @@ -0,0 +1,23 @@ +package org.signal.core.util + +/** + * Treats the string as a serialized list of tokens and tells you if an item is present in the list. + * In addition to exact matches, this handles wildcards at the end of an item. + * + * e.g. a,b,c*,d + */ +fun String.asListContains(item: String): Boolean { + val items: List = this + .split(",") + .map { it.trim() } + .filter { it.isNotEmpty() } + .toList() + + val exactMatches = items.filter { it.last() != '*' } + val prefixMatches = items.filter { it.last() == '*' } + + return exactMatches.contains(item) || + prefixMatches + .map { it.substring(0, it.length - 1) } + .any { item.startsWith(it) } +} diff --git a/app/src/test/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfigurationTest_inList.kt b/core-util/src/test/java/org/signal/core/util/StringExtensions_asListContains.kt similarity index 83% rename from app/src/test/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfigurationTest_inList.kt rename to core-util/src/test/java/org/signal/core/util/StringExtensions_asListContains.kt index 3f4b5a4a70..432d9bc5c4 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/service/webrtc/RingRtcDynamicConfigurationTest_inList.kt +++ b/core-util/src/test/java/org/signal/core/util/StringExtensions_asListContains.kt @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.service.webrtc +package org.signal.core.util import org.junit.Assert.assertEquals import org.junit.Test @@ -6,7 +6,7 @@ import org.junit.runner.RunWith import org.junit.runners.Parameterized @RunWith(Parameterized::class) -class RingRtcDynamicConfigurationTest_inList( +class StringExtensions_asListContains( private val model: String, private val serializedList: String, private val expected: Boolean @@ -14,7 +14,7 @@ class RingRtcDynamicConfigurationTest_inList( @Test fun testModelInList() { - val actual = RingRtcDynamicConfiguration.modelInList(model, serializedList) + val actual = serializedList.asListContains(model) assertEquals(expected, actual) }