fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v26.03.19 (#6411)

* fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v26.03.18

* Fix API breaks

* Add compatibility with rustls (#6367)

A new `rustls-platform-verifier-android` library has to be added to the project, it'll be called from Rust to get access to the certificates on Android.

Originally, this was supposed to be added as a local maven repo pointing to the rust crate that publishes the AAR, but that's just plain terrible (more details [here](https://github.com/rustls/rustls-platform-verifier#android).

Instead, what we can do is use a script that uses `cargo-download` to download the latest crate or a specified version, unzip it and add the `aar` file to the `:libraries:matrix:impl` module.

* Try fixing Sonar with local AAR files

* Remove `UserCertificatesProvider`: this is no longer needed after integrating rustls

* Added some docs for rustls and its `platform-verifier` library

* Upgrade SDK to `26.03.19`: this version contains a workaround that allows the app to use the same TLS verifier as before, fixing the Let's Encrypt issues we saw with some homeservers (like element.io)

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jorge Martín <jorgem@element.io>
This commit is contained in:
renovate[bot]
2026-03-20 16:20:37 +01:00
committed by GitHub
parent cb228e47b9
commit 643d1e957d
25 changed files with 86 additions and 127 deletions

View File

@@ -54,7 +54,7 @@ jobs:
with: with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }} cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
- name: Build debug code and test fixtures - name: Build debug code and test fixtures
run: ./gradlew assembleDebug createFullJarDebugTestFixtures :app:createFullJarGplayDebugTestFixtures $CI_GRADLE_ARG_PROPERTIES run: ./gradlew assembleGplayDebug createFullJarDebugTestFixtures :app:createFullJarGplayDebugTestFixtures $CI_GRADLE_ARG_PROPERTIES
- name: 🔊 Publish results to Sonar - name: 🔊 Publish results to Sonar
env: env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

View File

@@ -74,3 +74,6 @@
# Keep Metro classes # Keep Metro classes
-keep,allowoptimization,allowshrinking class dev.zacsweers.metro.** { *; } -keep,allowoptimization,allowshrinking class dev.zacsweers.metro.** { *; }
# Rustls Platform Verifier
-keep, includedescriptorclasses class org.rustls.platformverifier.** { *; }

View File

@@ -11,6 +11,7 @@
* [Rust SDK](#rust-sdk) * [Rust SDK](#rust-sdk)
* [Matrix Rust Component Kotlin](#matrix-rust-component-kotlin) * [Matrix Rust Component Kotlin](#matrix-rust-component-kotlin)
* [Building the SDK locally](#building-the-sdk-locally) * [Building the SDK locally](#building-the-sdk-locally)
* [rustls and platform verifier](#rustls-and-platform-verifier)
* [The Android project](#the-android-project) * [The Android project](#the-android-project)
* [Application](#application) * [Application](#application)
* [Jetpack Compose](#jetpack-compose) * [Jetpack Compose](#jetpack-compose)
@@ -160,6 +161,19 @@ Troubleshooting:
You can switch back to using the published version of the SDK by deleting `libraries/rustsdk/matrix-rust-sdk.aar`. You can switch back to using the published version of the SDK by deleting `libraries/rustsdk/matrix-rust-sdk.aar`.
#### rustls and platform verifier
The SDK uses [rustls](https://github.com/rustls/rustls) for TLS, which is a pure Rust implementation of TLS. In turn, this means we have to add the
`rustls-platform-verifier` library to our project, which provides platform-specific TLS certificate verification for rustls. This library uses the Android NDK's
`TrustManager` to verify TLS certificates on Android.
Though it's meant to be used through convoluted way of downloading the dependency, locating it in the
cargo folder and using that path as a local maven repo as described [here](https://github.com/rustls/rustls-platform-verifier#android), we have
added a script (`tools/sdk/update-rustls`) to download, unpack and add this AAR file locally to the `:libraries:matrix:impl` module instead.
When should we run this script? Whenever we update the `rustls` dependency in the Rust SDK, we should check if the version of `rustls-platform-verifier`
has changed as well, and if so, run this script to update the AAR file in our project. The SDK team should ping us when this happens.
### The Android project ### The Android project
The project should compile out of the box. The project should compile out of the box.

View File

@@ -196,6 +196,7 @@ class LinkNewDeviceFlowNode(
is ErrorType.ConnectionInsecure -> ErrorScreenType.InsecureChannelDetected is ErrorType.ConnectionInsecure -> ErrorScreenType.InsecureChannelDetected
is ErrorType.Expired -> ErrorScreenType.Expired is ErrorType.Expired -> ErrorScreenType.Expired
is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError
is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError
} }
// It is OK to push on backstack, since when user leaves the error screen, a new root will be set, // It is OK to push on backstack, since when user leaves the error screen, a new root will be set,
// or the whole flow will be popped. // or the whole flow will be popped.

View File

@@ -141,6 +141,7 @@ class QrCodeLoginFlowNode(
} }
QrLoginException.CheckCodeAlreadySent, QrLoginException.CheckCodeAlreadySent,
QrLoginException.CheckCodeCannotBeSent, QrLoginException.CheckCodeCannotBeSent,
QrLoginException.UnsupportedQrCodeType,
QrLoginException.Unknown -> { QrLoginException.Unknown -> {
Timber.e(error, "Unknown error found") Timber.e(error, "Unknown error found")
backstack.replace(NavTarget.Error(QrCodeErrorScreenType.UnknownError)) backstack.replace(NavTarget.Error(QrCodeErrorScreenType.UnknownError))

View File

@@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version
# https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt
# All new features should not be implemented in the pull request that upgrades the version, developers should # All new features should not be implemented in the pull request that upgrades the version, developers should
# only fix API breaks and may add some TODOs. # only fix API breaks and may add some TODOs.
matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.03.11" matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.03.19"
# Others # Others
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }

View File

@@ -20,5 +20,6 @@ sealed class QrLoginException : Exception() {
data object OtherDeviceNotSignedIn : QrLoginException() data object OtherDeviceNotSignedIn : QrLoginException()
data object CheckCodeAlreadySent : QrLoginException() data object CheckCodeAlreadySent : QrLoginException()
data object CheckCodeCannotBeSent : QrLoginException() data object CheckCodeCannotBeSent : QrLoginException()
data object UnsupportedQrCodeType : QrLoginException()
data object Unknown : QrLoginException() data object Unknown : QrLoginException()
} }

View File

@@ -23,6 +23,11 @@ sealed class ErrorType(message: String) : Exception(message) {
*/ */
class UnsupportedProtocol(message: String) : ErrorType(message) class UnsupportedProtocol(message: String) : ErrorType(message)
/**
* The QR code type is not supported by the client.
*/
class UnsupportedQrCodeType(message: String) : ErrorType(message)
/** /**
* Secrets backup not set up properly. * Secrets backup not set up properly.
*/ */

View File

@@ -28,6 +28,8 @@ dependencies {
} else { } else {
debugImplementation(libs.matrix.sdk) debugImplementation(libs.matrix.sdk)
} }
implementation(files("libs/rustls-platform-verifier-android.aar"))
implementation(projects.appconfig) implementation(projects.appconfig)
implementation(projects.libraries.androidutils) implementation(projects.libraries.androidutils)
implementation(projects.libraries.di) implementation(projects.libraries.di)

View File

@@ -0,0 +1 @@
Updated rustls-platform-verifier-android.aar using `rustls-platform-verifier-0.1.1.aar`

View File

@@ -17,7 +17,6 @@ import io.element.android.libraries.di.annotations.AppCoroutineScope
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.analytics.UtdTracker
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.SessionPaths
import io.element.android.libraries.matrix.impl.paths.getSessionPaths import io.element.android.libraries.matrix.impl.paths.getSessionPaths
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
@@ -57,7 +56,6 @@ class RustMatrixClientFactory(
private val coroutineDispatchers: CoroutineDispatchers, private val coroutineDispatchers: CoroutineDispatchers,
private val sessionStore: SessionStore, private val sessionStore: SessionStore,
private val userAgentProvider: UserAgentProvider, private val userAgentProvider: UserAgentProvider,
private val userCertificatesProvider: UserCertificatesProvider,
private val proxyProvider: ProxyProvider, private val proxyProvider: ProxyProvider,
private val clock: SystemClock, private val clock: SystemClock,
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
@@ -143,7 +141,6 @@ class RustMatrixClientFactory(
} }
.setSessionDelegate(sessionDelegate) .setSessionDelegate(sessionDelegate)
.userAgent(userAgentProvider.provide()) .userAgent(userAgentProvider.provide())
.addRootCertificates(userCertificatesProvider.provides())
.autoEnableBackups(true) .autoEnableBackups(true)
.autoEnableCrossSigning(true) .autoEnableCrossSigning(true)
.roomKeyRecipientStrategy( .roomKeyRecipientStrategy(

View File

@@ -13,19 +13,16 @@ import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker
import io.element.android.libraries.matrix.impl.ClientBuilderProvider import io.element.android.libraries.matrix.impl.ClientBuilderProvider
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
import timber.log.Timber import timber.log.Timber
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class RustHomeServerLoginCompatibilityChecker( class RustHomeServerLoginCompatibilityChecker(
private val clientBuilderProvider: ClientBuilderProvider, private val clientBuilderProvider: ClientBuilderProvider,
private val userCertificatesProvider: UserCertificatesProvider,
) : HomeServerLoginCompatibilityChecker { ) : HomeServerLoginCompatibilityChecker {
override suspend fun check(url: String): Result<Boolean> = runCatchingExceptions { override suspend fun check(url: String): Result<Boolean> = runCatchingExceptions {
clientBuilderProvider.provide() clientBuilderProvider.provide()
.inMemoryStore() .inMemoryStore()
.serverNameOrHomeserverUrl(url) .serverNameOrHomeserverUrl(url)
.addRootCertificates(userCertificatesProvider.provides())
.build() .build()
.use { .use {
it.homeserverLoginDetails() it.homeserverLoginDetails()

View File

@@ -46,5 +46,6 @@ object QrErrorMapper {
is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable
is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent
is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent
is RustHumanQrLoginException.UnsupportedQrCodeType -> QrLoginException.UnsupportedQrCodeType
} }
} }

View File

@@ -1,77 +0,0 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.certificates
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import timber.log.Timber
import java.security.KeyStore
import java.security.KeyStoreException
@ContributesBinding(AppScope::class)
class DefaultUserCertificatesProvider : UserCertificatesProvider {
/**
* Get additional user-installed certificates from the `AndroidCAStore` `Keystore`.
*
* The Rust HTTP client doesn't include user-installed certificates in its internal certificate
* store. This means that whatever the user installs will be ignored.
*
* While most users don't need user-installed certificates some special deployments or debugging
* setups using a proxy might want to use them.
*
* @return A list of byte arrays where each byte array is a single user-installed certificate
* in encoded form.
*/
override fun provides(): List<ByteArray> {
// At least for API 34 the `AndroidCAStore` `Keystore` type contained user certificates as well.
// I have not found this to be documented anywhere.
val keyStore: KeyStore = try {
KeyStore.getInstance("AndroidCAStore")
} catch (e: KeyStoreException) {
Timber.w(e, "Failed to get AndroidCAStore keystore")
return emptyList()
}
val aliases = try {
keyStore.load(null)
keyStore.aliases()
} catch (e: Exception) {
Timber.w(e, "Failed to load and get aliases AndroidCAStore keystore")
return emptyList()
}
return aliases.toList()
.filter { alias ->
// The certificate alias always contains the prefix `system` or
// `user` and the MD5 subject hash separated by a colon.
//
// The subject hash can be calculated using openssl as such:
// openssl x509 -subject_hash_old -noout -in mycert.cer
//
// Again, I have not found this to be documented somewhere.
alias.startsWith("user")
}
.mapNotNull { alias ->
try {
keyStore.getEntry(alias, null)
} catch (e: Exception) {
Timber.w(e, "Failed to get entry for alias $alias")
null
}
}
.filterIsInstance<KeyStore.TrustedCertificateEntry>()
.map { trustedCertificateEntry ->
trustedCertificateEntry.trustedCertificate.encoded
}
.also {
// Let's at least log the number of user-installed certificates we found,
// since the alias isn't particularly useful nor does the issuer seem to
// be easily available.
Timber.i("Found ${it.size} additional user-provided certificates.")
}
}
}

View File

@@ -1,13 +0,0 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.certificates
interface UserCertificatesProvider {
fun provides(): List<ByteArray>
}

View File

@@ -22,4 +22,5 @@ internal fun HumanQrGrantLoginException.map() = when (this) {
is HumanQrGrantLoginException.OtherDeviceAlreadySignedIn -> ErrorType.OtherDeviceAlreadySignedIn(message.orEmpty()) is HumanQrGrantLoginException.OtherDeviceAlreadySignedIn -> ErrorType.OtherDeviceAlreadySignedIn(message.orEmpty())
is HumanQrGrantLoginException.Unknown -> ErrorType.Unknown(message.orEmpty()) is HumanQrGrantLoginException.Unknown -> ErrorType.Unknown(message.orEmpty())
is HumanQrGrantLoginException.UnsupportedProtocol -> ErrorType.UnsupportedProtocol(message.orEmpty()) is HumanQrGrantLoginException.UnsupportedProtocol -> ErrorType.UnsupportedProtocol(message.orEmpty())
is HumanQrGrantLoginException.UnsupportedQrCodeType -> ErrorType.UnsupportedQrCodeType(message.orEmpty())
} }

View File

@@ -10,16 +10,19 @@ package io.element.android.libraries.matrix.impl.platform
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.platform.InitPlatformService import io.element.android.libraries.matrix.api.platform.InitPlatformService
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
import io.element.android.libraries.matrix.impl.tracing.map import io.element.android.libraries.matrix.impl.tracing.map
import org.matrix.rustcomponents.sdk.initPlatform import org.matrix.rustcomponents.sdk.initPlatform
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class RustInitPlatformService : InitPlatformService { class RustInitPlatformService(
private val buildMeta: BuildMeta,
) : InitPlatformService {
override fun init(tracingConfiguration: TracingConfiguration) { override fun init(tracingConfiguration: TracingConfiguration) {
initPlatform( initPlatform(
config = tracingConfiguration.map(), config = tracingConfiguration.map(buildMeta),
useLightweightTokioRuntime = false useLightweightTokioRuntime = false
) )
} }

View File

@@ -65,9 +65,8 @@ internal fun RoomListInterface.entriesFlow(
trySendBlocking(roomEntriesUpdate) trySendBlocking(roomEntriesUpdate)
} }
} }
val result = entriesWithDynamicAdaptersWith( val result = entriesWithDynamicAdapters(
pageSize = pageSize.toUInt(), pageSize = pageSize.toUInt(),
enableLatestEventSorter = true,
listener = listener, listener = listener,
) )
val controller = result.controller() val controller = result.controller()

View File

@@ -107,6 +107,10 @@ class TimelineEventContentMapper(
threadInfo = extractThreadInfo(it.content), threadInfo = extractThreadInfo(it.content),
) )
} }
is MsgLikeKind.LiveLocation -> {
// Live location messages are a special kind of message that we want to treat as unknown content for now
UnknownContent
}
is MsgLikeKind.Other -> UnknownContent is MsgLikeKind.Other -> UnknownContent
} }
} }
@@ -134,9 +138,6 @@ class TimelineEventContentMapper(
} }
is TimelineItemContent.CallInvite -> LegacyCallInviteContent is TimelineItemContent.CallInvite -> LegacyCallInviteContent
is TimelineItemContent.RtcNotification -> CallNotifyContent is TimelineItemContent.RtcNotification -> CallNotifyContent
is TimelineItemContent.LiveLocation -> {
UnknownContent
}
} }
} }
} }

View File

@@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.tracing.LogLevel
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
import io.element.android.libraries.matrix.api.tracing.TracingService import io.element.android.libraries.matrix.api.tracing.TracingService
import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
import org.matrix.rustcomponents.sdk.SentryConfig
import org.matrix.rustcomponents.sdk.TracingFileConfiguration import org.matrix.rustcomponents.sdk.TracingFileConfiguration
import org.matrix.rustcomponents.sdk.reloadTracingFileWriter import org.matrix.rustcomponents.sdk.reloadTracingFileWriter
import timber.log.Timber import timber.log.Timber
@@ -59,11 +60,17 @@ private fun WriteToFilesConfiguration.toTracingFileConfiguration(): TracingFileC
} }
} }
fun TracingConfiguration.map(): org.matrix.rustcomponents.sdk.TracingConfiguration = org.matrix.rustcomponents.sdk.TracingConfiguration( fun TracingConfiguration.map(buildMeta: BuildMeta): org.matrix.rustcomponents.sdk.TracingConfiguration = org.matrix.rustcomponents.sdk.TracingConfiguration(
writeToStdoutOrSystem = writesToLogcat, writeToStdoutOrSystem = writesToLogcat,
logLevel = logLevel.toRustLogLevel(), logLevel = logLevel.toRustLogLevel(),
extraTargets = extraTargets, extraTargets = extraTargets,
traceLogPacks = traceLogPacks.map(), traceLogPacks = traceLogPacks.map(),
writeToFiles = writesToFilesConfiguration.toTracingFileConfiguration(), writeToFiles = writesToFilesConfiguration.toTracingFileConfiguration(),
sentryDsn = sdkSentryDsn, sentryConfig = sdkSentryDsn?.let {
SentryConfig(
dsn = it,
appVersion = buildMeta.versionName,
appPlatform = "Android",
)
}
) )

View File

@@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider
import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider
import io.element.android.libraries.matrix.impl.room.FakeTimelineEventFilterFactory import io.element.android.libraries.matrix.impl.room.FakeTimelineEventFilterFactory
import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
@@ -58,7 +57,6 @@ fun TestScope.createRustMatrixClientFactory(
coroutineDispatchers = testCoroutineDispatchers(), coroutineDispatchers = testCoroutineDispatchers(),
sessionStore = sessionStore, sessionStore = sessionStore,
userAgentProvider = SimpleUserAgentProvider(), userAgentProvider = SimpleUserAgentProvider(),
userCertificatesProvider = FakeUserCertificatesProvider(),
proxyProvider = FakeProxyProvider(), proxyProvider = FakeProxyProvider(),
clock = FakeSystemClock(), clock = FakeSystemClock(),
analyticsService = FakeAnalyticsService(), analyticsService = FakeAnalyticsService(),

View File

@@ -1,17 +0,0 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
class FakeUserCertificatesProvider : UserCertificatesProvider {
override fun provides(): List<ByteArray> {
return emptyList()
}
}

View File

@@ -49,6 +49,5 @@ class RustHomeserverLoginCompatibilityCheckerTest {
FakeFfiClient(homeserverLoginDetailsResult = result) FakeFfiClient(homeserverLoginDetailsResult = result)
} }
}, },
userCertificatesProvider = FakeUserCertificatesProvider(),
) )
} }

35
tools/sdk/update-rustls Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Copyright (c) 2026 Element Creations Ltd.
#
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
# Please see LICENSE files in the repository root for full details.
set -e
set -u
VERSION=${1:-}
if [ -n "$VERSION" ]; then
PACKAGE=rustls-platform-verifier-android==$VERSION
else
PACKAGE=rustls-platform-verifier-android
fi
cargo install cargo-download
mkdir -p tmp/rustls-platform-verifier-android
cargo download $PACKAGE > tmp/rustls-platform-verifier-android/rustls-platform-verifier-android.gz
ROOT=$(git rev-parse --show-toplevel)
cd tmp/rustls-platform-verifier-android
echo "Extracting rustls-platform-verifier-android.aar from \`rustls-platform-verifier-android.gz\`"
tar -xzvf rustls-platform-verifier-android.gz &> /dev/null
DIR=$(find . -type d -name "rustls-platform-verifier-android-*")
AAR=$(find $DIR -type f -name "*.aar")
cp $AAR $ROOT/libraries/matrix/impl/libs/rustls-platform-verifier-android.aar
cd $ROOT
rm -r tmp/rustls-platform-verifier-android
echo "Updated rustls-platform-verifier-android.aar using \`$(basename $AAR)\`" > libraries/matrix/impl/libs/rustls-platform-verifier-android.aar.version
cat libraries/matrix/impl/libs/rustls-platform-verifier-android.aar.version