Skip to content

Conversation

@typfel
Copy link
Member

@typfel typfel commented Dec 3, 2025

What's new in this PR


PR Submission Checklist for internal contributors
  • The PR Title
    • conforms to the style of semantic commits messages¹ supported in Wire's Github Workflow²
    • contains a reference JIRA issue number like SQPIT-764
    • answers the question: If merged, this PR will: ... ³
  1. https://sparkbox.com/foundry/semantic_commit_messages
  2. https://github.com/wireapp/.github#usage
  3. E.g. feat(conversation-list): Sort conversations by most emojis in the title #SQPIT-764.

@typfel typfel requested a review from a team December 3, 2025 10:06
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

🐰 Bencher Report

Branchfeat/android-interop
Testbedubuntu-latest

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds flag.

Click to view all benchmark results
BenchmarkLatencymicroseconds (µs)
Commit add f(group size)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
18,278.00 µs
Commit add f(group size)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
755.18 µs
Commit add f(group size)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
4,383.60 µs
Commit add f(group size)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
7,852.80 µs
Commit add f(group size)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
11,955.00 µs
Commit add f(group size)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
14,937.00 µs
Commit add f(number clients)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
991,950.00 µs
Commit add f(number clients)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
728.52 µs
Commit add f(number clients)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
79,389.00 µs
Commit add f(number clients)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
216,990.00 µs
Commit add f(number clients)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
426,880.00 µs
Commit add f(number clients)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
684,740.00 µs
Commit pending proposals f(group size)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
116,340.00 µs
Commit pending proposals f(group size)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
22,931.00 µs
Commit pending proposals f(group size)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
41,660.00 µs
Commit pending proposals f(group size)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
57,573.00 µs
Commit pending proposals f(group size)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
77,346.00 µs
Commit pending proposals f(group size)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
92,995.00 µs
Commit pending proposals f(pending size)/cs1/mem/1📈 view plot
⚠️ NO THRESHOLD
18,649.00 µs
Commit pending proposals f(pending size)/cs1/mem/101📈 view plot
⚠️ NO THRESHOLD
115,170.00 µs
Commit pending proposals f(pending size)/cs1/mem/21📈 view plot
⚠️ NO THRESHOLD
35,042.00 µs
Commit pending proposals f(pending size)/cs1/mem/41📈 view plot
⚠️ NO THRESHOLD
56,164.00 µs
Commit pending proposals f(pending size)/cs1/mem/61📈 view plot
⚠️ NO THRESHOLD
75,509.00 µs
Commit pending proposals f(pending size)/cs1/mem/81📈 view plot
⚠️ NO THRESHOLD
95,026.00 µs
Commit remove f(group size)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
10,861.00 µs
Commit remove f(group size)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
578.25 µs
Commit remove f(group size)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
2,266.10 µs
Commit remove f(group size)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
4,072.00 µs
Commit remove f(group size)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
6,275.50 µs
Commit remove f(group size)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
8,165.30 µs
Commit remove f(number clients)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
13,781.00 µs
Commit remove f(number clients)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
135,430.00 µs
Commit remove f(number clients)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
111,170.00 µs
Commit remove f(number clients)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
86,927.00 µs
Commit remove f(number clients)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
62,610.00 µs
Commit remove f(number clients)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
38,179.00 µs
Commit update f(group size)/cs1/mem/1002📈 view plot
⚠️ NO THRESHOLD
135,440.00 µs
Commit update f(group size)/cs1/mem/2📈 view plot
⚠️ NO THRESHOLD
752.95 µs
Commit update f(group size)/cs1/mem/202📈 view plot
⚠️ NO THRESHOLD
27,989.00 µs
Commit update f(group size)/cs1/mem/402📈 view plot
⚠️ NO THRESHOLD
55,153.00 µs
Commit update f(group size)/cs1/mem/602📈 view plot
⚠️ NO THRESHOLD
82,762.00 µs
Commit update f(group size)/cs1/mem/802📈 view plot
⚠️ NO THRESHOLD
108,950.00 µs
🐰 View full continuous benchmarking report in Bencher

@typfel typfel force-pushed the feat/android-interop branch 14 times, most recently from db8ff8c to fe45bc1 Compare December 5, 2025 14:51
@fewerner
Copy link
Contributor

fewerner commented Dec 8, 2025

8debb0b appears to be empty

Copy link
Contributor

@fewerner fewerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! I think my main concern is the CI runtime. We should think about testing ios and android separately and in parallel. This would save time in setup and test run and have clear CI dependencies.

@istankovic
Copy link
Member

Nice commit sequencing and commit messages! 💜

@istankovic
Copy link
Member

istankovic commented Dec 8, 2025

Shouldn't we add all the android-interop files under interop, not crypto-ffi?

interop/
├── Cargo.toml
├── README.md
└── src
    ├── clients
    │   ├── corecrypto
    │   │   ├── android.rs
    │   │   ├── ffi.rs
    │   │   ├── ios.rs
    │   │   ├── mod.rs
    │   │   ├── native.rs
    │   │   └── web
    │   │       ├── mls.ts
    │   │       ├── mod.rs
    │   │       ├── populate.sh
    │   │       └── proteus.ts
    │   ├── InteropClient
    │   │   ├── install-interop-client.sh
    │   │   ├── InteropClient
    │   │   │   ├── Assets.xcassets
    │   │   │   │   ├── AccentColor.colorset
    │   │   │   │   │   └── Contents.json
    │   │   │   │   ├── AppIcon.appiconset
    │   │   │   │   │   └── Contents.json
    │   │   │   │   └── Contents.json
    │   │   │   ├── ContentView.swift
    │   │   │   ├── Info.plist
    │   │   │   ├── InteropAction.swift
    │   │   │   ├── InteropClientApp.swift
    │   │   │   └── Preview Content
    │   │   │       └── Preview Assets.xcassets
    │   │   │           └── Contents.json
    │   │   └── InteropClient.xcodeproj
    │   │       ├── project.pbxproj
    │   │       └── project.xcworkspace
    │   │           └── contents.xcworkspacedata
    │   └── mod.rs
    ├── main.rs
    └── util.rs

We already have Swift interop client here so it would make sense to have Android too.

@istankovic
Copy link
Member

There's a warning in https://github.com/wireapp/core-crypto/actions/runs/19966647475/job/57260303169:

> Task :android-interop:processReleaseMainManifest
/Users/cc-ghrunner-1/runner/work/core-crypto/core-crypto/crypto-ffi/bindings/android-interop/src/main/AndroidManifest.xml:18:17-75 Warning:
	Element category#android.intent.category.DEFAULT at AndroidManifest.xml:18:17-75 duplicated with element declared at AndroidManifest.xml:16:17-75

@typfel
Copy link
Member Author

typfel commented Dec 8, 2025

Shouldn't we add all the android-interop files under interop, not crypto-ffi?

interop/
├── Cargo.toml
├── README.md
└── src
    ├── clients
    │   ├── corecrypto
    │   │   ├── android.rs
    │   │   ├── ffi.rs
    │   │   ├── ios.rs
    │   │   ├── mod.rs
    │   │   ├── native.rs
    │   │   └── web
    │   │       ├── mls.ts
    │   │       ├── mod.rs
    │   │       ├── populate.sh
    │   │       └── proteus.ts
    │   ├── InteropClient
    │   │   ├── install-interop-client.sh
    │   │   ├── InteropClient
    │   │   │   ├── Assets.xcassets
    │   │   │   │   ├── AccentColor.colorset
    │   │   │   │   │   └── Contents.json
    │   │   │   │   ├── AppIcon.appiconset
    │   │   │   │   │   └── Contents.json
    │   │   │   │   └── Contents.json
    │   │   │   ├── ContentView.swift
    │   │   │   ├── Info.plist
    │   │   │   ├── InteropAction.swift
    │   │   │   ├── InteropClientApp.swift
    │   │   │   └── Preview Content
    │   │   │       └── Preview Assets.xcassets
    │   │   │           └── Contents.json
    │   │   └── InteropClient.xcodeproj
    │   │       ├── project.pbxproj
    │   │       └── project.xcworkspace
    │   │           └── contents.xcworkspacedata
    │   └── mod.rs
    ├── main.rs
    └── util.rs

We already have Swift interop client here so it would make sense to have Android too.

I had it in the interop directory initially but that doesn't very well when I want to include the core crypto bindings as a project dependency, it needs to be in the same gradle project (crypto-ffi/bindings).

My plan is to also move the iOS and web interop clients to the bindings directory.

@istankovic
Copy link
Member

I had it in the interop directory initially but that doesn't very well when I want to include the core crypto bindings as a project dependency, it needs to be in the same gradle project (crypto-ffi/bindings).

That is surprising. Doesn't gradle support path dependencies?

My plan is to also move the iOS and web interop clients to the bindings directory.

I would rather not we do that. I think we should retain a clear separation between bindings and interop.

@istankovic
Copy link
Member

Running cargo run --bin interop results in a stuck process on my machine:
Screenshot_20251208_135511

@typfel
Copy link
Member Author

typfel commented Dec 8, 2025

8debb0b appears to be empty

it was accidently moved to 19da4bb

I'll split it up again.

@typfel
Copy link
Member Author

typfel commented Dec 8, 2025

Running cargo run --bin interop results in a stuck process on my machine: Screenshot_20251208_135511

Running the interop currently assumes the android emulator and the iOS emulator is already running.

@typfel typfel force-pushed the feat/android-interop branch from 7a9475f to 1709179 Compare December 8, 2025 13:39
Copy link
Member

@istankovic istankovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start, but it still needs more work. In particular, we should keep the interop code separate from the bindings.

@typfel typfel force-pushed the feat/android-interop branch from e5d3ac1 to 6fbd19b Compare December 17, 2025 22:41
@istankovic
Copy link
Member

Could you please split commit b0559ee0d5e8f8404cdb68797d0d9907b1c31c0a into changes that only touch crypto-ffi and changes that are about the new interop client?

The changes touching only crypto-ffi seem to have no relation to the new interop client, from what I can tell.

includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block seems to be unnecessary.

}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be set to VERSION_17 to be consistent with crypto-ffi.

compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this kotlin block?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was part of the default project. Are you saying it's unnecessary specify which jvm we are targeting?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we can just omit the whole kotlin block. 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting errors about conflicting JVM versions if I remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange, it works for me. Did you make sure to sync the compileOptions above with those of crypto-ffi?
I have this:

diff --git a/interop/src/clients/android-interop/build.gradle.kts b/interop/src/clients/android-interop/build.gradle.kts
index 45518ebfc..0aca03fdd 100644
--- a/interop/src/clients/android-interop/build.gradle.kts
+++ b/interop/src/clients/android-interop/build.gradle.kts
@@ -25,13 +25,8 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_11
-        targetCompatibility = JavaVersion.VERSION_11
-    }
-    kotlin {
-        compilerOptions {
-            jvmTarget.set(JvmTarget.JVM_11)
-        }
+        sourceCompatibility = JavaVersion.VERSION_17
+        targetCompatibility = JavaVersion.VERSION_17
     }
 }

# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed with AGP 8.0+ so we can drop this block.

android.enableJetifier=true

# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary to explicitly write, I think official is the default.


<application
android:allowBackup="false"
android:supportsRtl="true">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we don't need to set these two attributes.

android:label="AndroidInterop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we don't actually need action.MAIN and category.LAUNCHER -- this is essentially a background service, not a regular app that has a launcher etc.

Copy link
Member Author

@typfel typfel Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need it because you can't launch the application without this intent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is it possible then that the tests pass without it?

Copy link
Member Author

@typfel typfel Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK maybe you right the interop doesn't need it, but for debugging purposes it's very convenient to be able to launch the interop client in the debugger.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're using a graphical debugger? I guess it makes sense to keep it then, if it makes debugging easier. 👍

@@ -0,0 +1,434 @@
use std::{
cell::{Cell, RefCell},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cell import should be guarded via #[cfg(feature = "proteus")] in order to silence the unused import warning.

@@ -0,0 +1,434 @@
use std::{
cell::{Cell, RefCell},
io::{BufRead, BufReader, Read},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traits should be imported ... as _, e.g. BufRead as _, ....

match process.try_wait() {
Ok(None) => {}
Ok(Some(exit_status)) => {
if boot_device && exit_status.code() == Some(149) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does 149 mean here?

}

fn boot_device(device: &str) -> std::io::Result<Output> {
Command::new("xcrun").args(["simctl", "boot", device]).output()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xcrun is only available with XCode, how is this supposed to work on other platforms?

.execute(format!(
"--es action init-mls --es client_id {} --ei ciphersuite {}",
client_id_base64, ciphersuite
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this could also be written as

.execute(format!(
 "--es action init-mls --es client_id {client_id_base64} --ei ciphersuite {ciphersuite}"
))

use base64::{Engine as _, engine::general_purpose};
use core_crypto::{KeyPackageIn, Keypackage};
use thiserror::Error;
use tls_codec::Deserialize;
Copy link
Member

@istankovic istankovic Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: traits should be imported .. as _.

pid.as_str(),
"-v",
"raw",
"System.out:I *:S",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I didn't know one can get system logs so easily!

Nit: it would be nice to have a short comment explaining the meaning of

System.out:I *:S

Failure { message: String },
}

#[derive(Error, Debug)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd prefer thiserror::Error here rather than just plain Error, which is one of std traits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants