Give the native call component its view of Matrix

The factory lives in libraries/matrix/impl because that is the only module compiled against the Rust SDK, and is app-scoped because a call is started for whichever account it belongs to rather than the one on screen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Valere
2026-09-22 21:04:04 +02:00
committed by Valere Fedronic
parent 0d36f70c96
commit 43a1364671
4 changed files with 108 additions and 3 deletions
+33 -2
View File
@@ -20,16 +20,47 @@ android {
setupDependencyInjection()
// Temporary: `-PelementCallLocalVersion` points this at a locally published build of
// element-call-android, because the library has no remote repository yet. Goes with the mavenLocal
// block in settings.gradle.kts. Only the BOM carries a version; every other artifact follows it.
val elementCallVersion: String = providers.gradleProperty("elementCallLocalVersion")
.getOrElse(libs.versions.element.call.get())
val usesLocalRustSdk = file("${rootDir.path}/libraries/rustsdk/matrix-rust-sdk.aar").exists()
if (usesLocalRustSdk) {
// element-call-matrix declares the Rust SDK as an ordinary Maven dependency, so with the local
// AAR in place a debug classpath would carry two copies of org.matrix.rustcomponents.sdk.
// Point the library's dependency at the same local AAR the app is using.
configurations.matching { it.name.startsWith("debug") }.configureEach {
resolutionStrategy.dependencySubstitution {
substitute(module("org.matrix.rustcomponents:sdk-android"))
.using(project(":libraries:rustsdk"))
.because("the local Rust SDK AAR replaces the published one on debug builds")
}
}
}
dependencies {
releaseImplementation(libs.matrix.sdk)
if (file("${rootDir.path}/libraries/rustsdk/matrix-rust-sdk.aar").exists()) {
println("\nNote: Using local binary of the Rust SDK.\n")
if (usesLocalRustSdk) {
println(
"\nNote: Using local binary of the Rust SDK." +
"\n element-call-matrix is substituted onto it as well, so the native call runs" +
"\n against this SDK rather than the one it was published against.\n"
)
debugImplementation(projects.libraries.rustsdk)
} else {
debugImplementation(libs.matrix.sdk)
}
implementation(variantOf(libs.rustls.platform.verifier) { artifactType("aar") })
// The native call's Matrix transport. Only this module may hand it a raw SDK client.
implementation(platform("io.element.android:element-call-bom:$elementCallVersion"))
implementation(libs.element.call.api)
implementation(projects.features.callnative.api)
implementation(libs.element.call.matrix)
implementation(projects.appconfig)
implementation(projects.features.enterprise.api)
implementation(projects.libraries.androidutils)
@@ -0,0 +1,38 @@
/*
* 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.
*/
package io.element.android.libraries.matrix.impl.di
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.call.api.matrix.ElementCallMatrixTransport
import io.element.android.call.matrix.ElementCallSdkTransport
import io.element.android.features.callnative.api.ElementCallTransportFactory
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.impl.RustMatrixClient
/**
* Gives the native call component its view of Matrix.
*
* Here because this is the only module in the app compiled against the Rust SDK, and the component's
* turnkey transport needs a raw SDK client. No feature module ever sees the SDK, the rule that no
* feature depends on `libraries/matrix/impl` still holds, and the SDK version contract is checked where
* the app's own SDK pin lives.
*
* The transport is built on the client's own coroutine scope, which is what ties it to the session: the
* component has no shutdown of its own, so cancelling that scope at logout is the only thing that stops
* the RTC core and its to-device subscription.
*/
@ContributesBinding(AppScope::class)
class DefaultElementCallTransportFactory : ElementCallTransportFactory {
override fun create(client: MatrixClient): ElementCallMatrixTransport {
return ElementCallSdkTransport(
client = (client as RustMatrixClient).innerClient,
sessionScope = client.sessionCoroutineScope,
)
}
}