From 09c07f0707411fdedec82446f037d3627172dc8c Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Fri, 6 Feb 2026 10:22:45 -0500 Subject: [PATCH] Fix benchmark tests. --- .../org/signal/benchmark/setup/TestUsers.kt | 3 +- .../securesms/util/Environment.kt | 2 +- .../securesms/util/SignalTrace.kt | 10 +- benchmark/build.gradle.kts | 2 + .../benchmark/BaselineProfileGenerator.kt | 8 +- .../benchmark/ConversationBenchmarks.kt | 2 + .../benchmark/StartupBenchmarks.kt | 2 + gradle/benchmark-libs.versions.toml | 10 +- gradle/verification-metadata.xml | 167 ++++++++++++++++++ microbenchmark/build.gradle.kts | 3 + .../InMemorySignalServiceAccountDataStore.kt | 2 +- .../java/org/signal/util/SignalClient.kt | 27 ++- 12 files changed, 211 insertions(+), 27 deletions(-) diff --git a/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt b/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt index 537c9d0db9..e7f6c8e234 100644 --- a/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt +++ b/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt @@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUti import org.thoughtcrime.securesms.registration.data.RegistrationData import org.thoughtcrime.securesms.registration.data.RegistrationRepository import org.thoughtcrime.securesms.registration.util.RegistrationUtil +import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.api.profiles.SignalServiceProfile import org.whispersystems.signalservice.api.push.SignalServiceAddress @@ -76,7 +77,7 @@ object TestUsers { SignalStore.registration.restoreDecisionState = RestoreDecisionState.Skipped RegistrationUtil.maybeMarkRegistrationComplete() SignalDatabase.recipients.setProfileName(Recipient.self().id, ProfileName.fromParts("Tester", "McTesterson")) - + TextSecurePreferences.setPromptedOptimizeDoze(application, true) return Recipient.self() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Environment.kt b/app/src/main/java/org/thoughtcrime/securesms/util/Environment.kt index 25dcd3b62f..acf7535563 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Environment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/Environment.kt @@ -11,7 +11,7 @@ object Environment { const val IS_STAGING: Boolean = BuildConfig.BUILD_ENVIRONMENT_TYPE == "Staging" || BuildConfig.BUILD_ENVIRONMENT_TYPE == "Pnp" || BuildConfig.BUILD_ENVIRONMENT_TYPE == "Backup" const val IS_NIGHTLY: Boolean = BuildConfig.BUILD_DISTRIBUTION_TYPE == "nightly" const val IS_WEBSITE: Boolean = BuildConfig.BUILD_DISTRIBUTION_TYPE == "website" - const val IS_INSTRUMENTATION: Boolean = BuildConfig.BUILD_VARIANT_TYPE == "Instrumentation" + const val IS_INSTRUMENTATION: Boolean = BuildConfig.BUILD_VARIANT_TYPE == "Instrumentation" || BuildConfig.BUILD_VARIANT_TYPE == "Benchmark" object Backups { @JvmStatic diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SignalTrace.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SignalTrace.kt index 99a0cb3336..5aad2057fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SignalTrace.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SignalTrace.kt @@ -1,21 +1,15 @@ package org.thoughtcrime.securesms.util import org.thoughtcrime.securesms.BuildConfig -import java.util.concurrent.Executors import androidx.tracing.Trace as AndroidTrace object SignalTrace { - - private val executor by lazy(LazyThreadSafetyMode.NONE) { - Executors.newSingleThreadExecutor() - } - @JvmStatic fun beginSection(methodName: String) { if (!BuildConfig.TRACING_ENABLED) { return } - executor.execute { AndroidTrace.beginSection(methodName) } + AndroidTrace.beginSection(methodName) } @JvmStatic @@ -23,6 +17,6 @@ object SignalTrace { if (!BuildConfig.TRACING_ENABLED) { return } - executor.execute { AndroidTrace.endSection() } + AndroidTrace.endSection() } } diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index 94834d4790..59d3745477 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -32,6 +32,8 @@ android { missingDimensionStrategy("environment", "prod") missingDimensionStrategy("distribution", "play") + + testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR" } buildTypes { diff --git a/benchmark/src/main/java/org/thoughtcrime/benchmark/BaselineProfileGenerator.kt b/benchmark/src/main/java/org/thoughtcrime/benchmark/BaselineProfileGenerator.kt index cd86fc3941..5db5b0a744 100644 --- a/benchmark/src/main/java/org/thoughtcrime/benchmark/BaselineProfileGenerator.kt +++ b/benchmark/src/main/java/org/thoughtcrime/benchmark/BaselineProfileGenerator.kt @@ -1,8 +1,6 @@ -@file:OptIn(ExperimentalBaselineProfilesApi::class) - package org.thoughtcrime.benchmark -import androidx.benchmark.macro.ExperimentalBaselineProfilesApi +import androidx.annotation.RequiresApi import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.test.uiautomator.By import androidx.test.uiautomator.Until @@ -16,7 +14,7 @@ import org.junit.Test * - start the app * - open a conversation */ -@OptIn(ExperimentalBaselineProfilesApi::class) +@RequiresApi(28) class BaselineProfileGenerator { @get:Rule val baselineProfileRule = BaselineProfileRule() @@ -24,7 +22,7 @@ class BaselineProfileGenerator { @Test fun startup() { var setup = false - baselineProfileRule.collectBaselineProfile( + baselineProfileRule.collect( packageName = "org.thoughtcrime.securesms", profileBlock = { if (!setup) { diff --git a/benchmark/src/main/java/org/thoughtcrime/benchmark/ConversationBenchmarks.kt b/benchmark/src/main/java/org/thoughtcrime/benchmark/ConversationBenchmarks.kt index 61aaabd84a..a06959dc33 100644 --- a/benchmark/src/main/java/org/thoughtcrime/benchmark/ConversationBenchmarks.kt +++ b/benchmark/src/main/java/org/thoughtcrime/benchmark/ConversationBenchmarks.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.benchmark import android.Manifest import android.os.Build +import androidx.annotation.RequiresApi import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.ExperimentalMetricApi import androidx.benchmark.macro.TraceSectionMetric @@ -14,6 +15,7 @@ import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) +@RequiresApi(31) class ConversationBenchmarks { @get:Rule val benchmarkRule = MacrobenchmarkRule() diff --git a/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt b/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt index 730c3abaf2..157feac29a 100644 --- a/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt +++ b/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.benchmark +import androidx.annotation.RequiresApi import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.ExperimentalMetricApi import androidx.benchmark.macro.StartupMode @@ -17,6 +18,7 @@ import org.junit.runner.RunWith * WARNING! THIS WILL WIPE YOUR SIGNAL INSTALL */ @RunWith(AndroidJUnit4::class) +@RequiresApi(31) class StartupBenchmarks { @get:Rule val benchmarkRule = MacrobenchmarkRule() diff --git a/gradle/benchmark-libs.versions.toml b/gradle/benchmark-libs.versions.toml index 9eb590ee01..caab25f5ec 100644 --- a/gradle/benchmark-libs.versions.toml +++ b/gradle/benchmark-libs.versions.toml @@ -2,12 +2,12 @@ # ./gradlew --write-verification-metadata sha256 qa --rerun-tasks [versions] -androidx-test-ext-junit = "1.1.5" +androidx-test-ext-junit = "1.3.0" [libraries] # Macrobench/Baseline profiles androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-test-ext-junit" } -espresso-core = "androidx.test.espresso:espresso-core:3.4.0" -uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0" -androidx-benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.1.1" -androidx-benchmark-micro = "androidx.benchmark:benchmark-junit4:1.1.0-beta04" +espresso-core = "androidx.test.espresso:espresso-core:3.7.0" +uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0" +androidx-benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.4.1" +androidx-benchmark-micro = "androidx.benchmark:benchmark-junit4:1.4.1" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 39e7eda758..11eb729340 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -290,6 +290,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -411,6 +416,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -583,6 +596,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -607,6 +628,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -619,6 +648,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -631,6 +668,30 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + + + + + + + + + @@ -7363,6 +7424,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7394,6 +7460,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7415,6 +7486,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7429,6 +7505,16 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + @@ -7443,6 +7529,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7471,6 +7562,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7483,6 +7579,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7502,6 +7603,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -7516,6 +7622,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -7583,6 +7697,30 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + + + + + + + + + @@ -11525,6 +11663,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -11601,6 +11747,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -11795,6 +11946,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -11807,6 +11966,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + diff --git a/microbenchmark/build.gradle.kts b/microbenchmark/build.gradle.kts index f236556f6e..9a9475dcca 100644 --- a/microbenchmark/build.gradle.kts +++ b/microbenchmark/build.gradle.kts @@ -23,6 +23,9 @@ android { defaultConfig { minSdk = libs.versions.minSdk.get().toInt() + + testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR" + testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } diff --git a/microbenchmark/src/androidTest/java/org/signal/util/InMemorySignalServiceAccountDataStore.kt b/microbenchmark/src/androidTest/java/org/signal/util/InMemorySignalServiceAccountDataStore.kt index d9951bbe3a..c4444add38 100644 --- a/microbenchmark/src/androidTest/java/org/signal/util/InMemorySignalServiceAccountDataStore.kt +++ b/microbenchmark/src/androidTest/java/org/signal/util/InMemorySignalServiceAccountDataStore.kt @@ -136,7 +136,7 @@ class InMemorySignalServiceAccountDataStore : SignalServiceAccountDataStore { } override fun storeKyberPreKey(kyberPreKeyId: Int, record: KyberPreKeyRecord?) { - error("Not used") + kyberPreKeys[kyberPreKeyId] = record!! } override fun containsKyberPreKey(kyberPreKeyId: Int): Boolean { diff --git a/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt b/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt index 53da9a15f7..a93e5842e3 100644 --- a/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt +++ b/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt @@ -15,6 +15,7 @@ import org.signal.libsignal.protocol.groups.GroupSessionBuilder import org.signal.libsignal.protocol.kem.KEMKeyPair import org.signal.libsignal.protocol.kem.KEMKeyType import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage +import org.signal.libsignal.protocol.state.KyberPreKeyRecord import org.signal.libsignal.protocol.state.PreKeyBundle import org.signal.libsignal.protocol.state.PreKeyRecord import org.signal.libsignal.protocol.state.SignedPreKeyRecord @@ -161,11 +162,12 @@ class SignalClient { timestamp = sentTimestamp ) ) - val destinations = others.map { bob -> - SignalProtocolAddress(bob.aci.toString(), 1) + val destinations = others.map { other -> + SignalProtocolAddress(other.aci.toString(), 1) } + val sessionMap = store.getAllAddressesWithActiveSessions(destinations.map { it.name }) - return cipher.encryptForGroup(distributionId, destinations, null, senderCertificate, content.encode(), ContentHint.DEFAULT, groupId) + return cipher.encryptForGroup(distributionId, destinations, sessionMap, senderCertificate, content.encode(), ContentHint.DEFAULT, groupId) } fun decryptMessage(envelope: Envelope) { @@ -177,14 +179,27 @@ class SignalClient { val preKeyRecord = PreKeyRecord(prekeyId, ECKeyPair.generate()) val signedPreKeyPair = ECKeyPair.generate() val signedPreKeySignature = store.identityKeyPair.privateKey.calculateSignature(signedPreKeyPair.publicKey.serialize()) - val kyerPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024) + + val kyberPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024) + val kyberPreKeyRecord = KyberPreKeyRecord(prekeyId, System.currentTimeMillis() - 10, kyberPair, store.identityKeyPair.privateKey.calculateSignature(kyberPair.publicKey.serialize())) store.storePreKey(prekeyId, preKeyRecord) store.storeSignedPreKey(prekeyId, SignedPreKeyRecord(prekeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature)) + store.storeKyberPreKey(prekeyId, kyberPreKeyRecord) + return PreKeyBundle( - prekeyId, prekeyId, prekeyId, preKeyRecord.keyPair.publicKey, prekeyId, signedPreKeyPair.publicKey, signedPreKeySignature, store.identityKeyPair.publicKey, - PreKeyBundle.NULL_PRE_KEY_ID, kyerPair.publicKey, kyerPair.secretKey.serialize() + registrationId = prekeyId, + deviceId = 1, + preKeyId = prekeyId, + preKeyPublic = preKeyRecord.keyPair.publicKey, + signedPreKeyId = prekeyId, + signedPreKeyPublic = signedPreKeyPair.publicKey, + signedPreKeySignature = signedPreKeySignature, + identityKey = store.identityKeyPair.publicKey, + kyberPreKeyId = kyberPreKeyRecord.id, + kyberPreKeyPublic = kyberPreKeyRecord.keyPair.publicKey, + kyberPreKeySignature = kyberPreKeyRecord.signature ) } }