Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions device-info/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use std::fmt;
#[cfg_attr(not(target_arch = "wasm32"), path = "native/mod.rs")]
mod imp;

#[cfg(target_os = "android")]
pub use imp::android;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DeviceType {
Expand Down
30 changes: 18 additions & 12 deletions device-info/src/native/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,38 @@ use jni::objects::{GlobalRef, JObject, JValue};
use jni::JavaVM;
use std::sync::OnceLock;

struct AndroidContext {
vm: JavaVM,
context: GlobalRef,
}
static ANDROID_VM: OnceLock<JavaVM> = OnceLock::new();
static ANDROID_CONTEXT: OnceLock<GlobalRef> = OnceLock::new();

static ANDROID_CONTEXT: OnceLock<AndroidContext> = OnceLock::new();
/// Initialize with just the JavaVM. Sufficient for reading `Build.*` fields (model,
/// manufacturer). Call from `JNI_OnLoad` where no application `Context` is available.
pub fn init_vm(vm: &JavaVM) {
let vm = unsafe { JavaVM::from_raw(vm.get_java_vm_pointer()).unwrap() };
let _ = ANDROID_VM.set(vm);
}

/// Initialize the Android JNI context. Must be called before `device_info()`.
///
/// Typically called from `JNI_OnLoad` or early in your Android application's lifecycle.
/// Initialize with both the JavaVM and an application `Context`.
/// Provides full functionality including device name resolution via `Settings.Global`.
pub fn init(vm: &JavaVM, context: JObject) {
let vm = unsafe { JavaVM::from_raw(vm.get_java_vm_pointer()).unwrap() };
let mut env = vm.get_env().expect("failed to get JNI env");
let context = env.new_global_ref(context).expect("failed to create global ref");
let _ = ANDROID_CONTEXT.set(AndroidContext { vm, context });
let _ = ANDROID_VM.set(vm);
let _ = ANDROID_CONTEXT.set(context);
}

pub fn device_info() -> Result<DeviceInfo, DeviceInfoError> {
let ctx = ANDROID_CONTEXT.get().ok_or(DeviceInfoError::NotInitialized)?;
let vm = ANDROID_VM.get().ok_or(DeviceInfoError::NotInitialized)?;

let mut env =
ctx.vm.attach_current_thread().map_err(|e| DeviceInfoError::Jni(e.to_string()))?;
vm.attach_current_thread().map_err(|e| DeviceInfoError::Jni(e.to_string()))?;

let model = get_build_field(&mut env, "MODEL")?;
let manufacturer = get_build_field(&mut env, "MANUFACTURER")?;
let name = get_device_name(&mut env, &ctx.context).unwrap_or_else(|_| model.clone());
let name = ANDROID_CONTEXT
.get()
.and_then(|ctx| get_device_name(&mut env, ctx).ok())
.unwrap_or_else(|| model.clone());
let device_type = detect_device_type(&manufacturer);

Ok(DeviceInfo { model, name, device_type })
Expand Down
1 change: 1 addition & 0 deletions livekit-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ isahc = { version = "1.7.2", default-features = false, features = [ "json", "tex
scopeguard = "1.2.0"
rand = { workspace = true }
os_info = "3.14.0"
device-info = { workspace = true }

[dev-dependencies]
tokio = { workspace = true, features = ["rt", "rt-multi-thread", "net", "time", "macros", "io-util"] }
16 changes: 8 additions & 8 deletions livekit-api/src/signal_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ pub struct SignalOptions {
pub single_peer_connection: bool,
/// Timeout for each individual signal connection attempt
pub connect_timeout: Duration,
/// Device model string for ClientInfo (e.g. "MacBookPro18,3")
pub device_model: Option<String>,
}

impl Default for SignalOptions {
Expand All @@ -113,7 +111,6 @@ impl Default for SignalOptions {
sdk_options: SignalSdkOptions::default(),
single_peer_connection: false,
connect_timeout: SIGNAL_CONNECT_TIMEOUT,
device_model: None,
}
}
}
Expand Down Expand Up @@ -559,6 +556,7 @@ fn create_join_request_param(
participant_sid: &str,
os: String,
os_version: String,
device_model: String,
) -> String {
let connection_settings = proto::ConnectionSettings {
auto_subscribe: options.auto_subscribe,
Expand All @@ -572,7 +570,7 @@ fn create_join_request_param(
protocol: PROTOCOL_VERSION as i32,
os,
os_version,
device_model: options.device_model.clone().unwrap_or_default(),
device_model,
..Default::default()
};

Expand Down Expand Up @@ -645,6 +643,10 @@ fn get_livekit_url(
}

let os_info = os_info::get();
let device_model = device_info::device_info()
.map(|info| info.model)
.unwrap_or_default();

if use_v1_path {
// For v1 path (single PC mode): only join_request param
// All other info (sdk, protocol, auto_subscribe, etc.) is inside the JoinRequest protobuf
Expand All @@ -655,6 +657,7 @@ fn get_livekit_url(
participant_sid,
os_info.os_type().to_string(),
os_info.version().to_string(),
device_model.to_string(),
);
lk_url.query_pairs_mut().append_pair("join_request", &join_request_param);
} else {
Expand All @@ -664,6 +667,7 @@ fn get_livekit_url(
.append_pair("sdk", options.sdk_options.sdk.as_str())
.append_pair("os", os_info.os_type().to_string().as_str())
.append_pair("os_version", os_info.version().to_string().as_str())
.append_pair("device_model", device_model.to_string().as_str())
.append_pair("protocol", PROTOCOL_VERSION.to_string().as_str())
.append_pair("auto_subscribe", if options.auto_subscribe { "1" } else { "0" })
.append_pair("adaptive_stream", if options.adaptive_stream { "1" } else { "0" });
Expand All @@ -672,10 +676,6 @@ fn get_livekit_url(
lk_url.query_pairs_mut().append_pair("version", sdk_version.as_str());
}

if let Some(device_model) = &options.device_model {
lk_url.query_pairs_mut().append_pair("device_model", device_model.as_str());
}

// For reconnects in v0 path, add reconnect and sid as separate query parameters
if reconnect {
lk_url
Expand Down
1 change: 1 addition & 0 deletions livekit-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ from_variants = "1.0.2"
[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21.1"
link-cplusplus = { version = "1", features = ["nothing"] }
device-info = { workspace = true }

[build-dependencies]
prost-build = { workspace = true }
Expand Down
14 changes: 1 addition & 13 deletions livekit-ffi/src/cabi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ pub unsafe extern "C" fn livekit_ffi_initialize(
capture_logs: bool,
sdk: *const c_char,
sdk_version: *const c_char,
device_model: *const c_char,
) {
FFI_SERVER.setup(FfiConfig {
callback_fn: Arc::new(move |event| {
Expand All @@ -46,18 +45,6 @@ pub unsafe extern "C" fn livekit_ffi_initialize(
capture_logs,
sdk: CStr::from_ptr(sdk).to_string_lossy().into_owned(),
sdk_version: CStr::from_ptr(sdk_version).to_string_lossy().into_owned(),
device_model: {
if device_model.is_null() {
None
} else {
let s = CStr::from_ptr(device_model).to_string_lossy().into_owned();
if s.is_empty() {
None
} else {
Some(s)
}
}
},
});

log::info!("initializing ffi server v{}", env!("CARGO_PKG_VERSION"));
Expand Down Expand Up @@ -139,6 +126,7 @@ pub mod android {
pub extern "C" fn JNI_OnLoad(vm: JavaVM, _: *mut c_void) -> jint {
println!("JNI_OnLoad, initializing LiveKit");
livekit::webrtc::android::initialize_android(&vm);
device_info::android::init_vm(&vm);
JNI_VERSION_1_6
}
}
1 change: 0 additions & 1 deletion livekit-ffi/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ pub struct FfiConfig {
pub capture_logs: bool,
pub sdk: String,
pub sdk_version: String,
pub device_model: Option<String>,
}

/// To make sure we use the right types, only types that implement this trait
Expand Down
1 change: 0 additions & 1 deletion livekit-ffi/src/server/room.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ impl FfiRoom {
if let Some(c) = config.as_ref() {
options.sdk_options.sdk = c.sdk.clone();
options.sdk_options.sdk_version = c.sdk_version.clone();
options.device_model = c.device_model.clone();
}
}

Expand Down
4 changes: 0 additions & 4 deletions livekit/src/room/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,6 @@ pub struct RoomOptions {
pub single_peer_connection: bool,
/// Timeout for each individual signal connection attempt
pub connect_timeout: Duration,
/// Device model string for ClientInfo (e.g. "MacBookPro18,3")
pub device_model: Option<String>,
}

impl Default for RoomOptions {
Expand All @@ -407,7 +405,6 @@ impl Default for RoomOptions {
sdk_options: RoomSdkOptions::default(),
single_peer_connection: false,
connect_timeout: SIGNAL_CONNECT_TIMEOUT,
device_model: None,
}
}
}
Expand Down Expand Up @@ -503,7 +500,6 @@ impl Room {
signal_options.adaptive_stream = options.adaptive_stream;
signal_options.single_peer_connection = options.single_peer_connection;
signal_options.connect_timeout = options.connect_timeout;
signal_options.device_model = options.device_model.clone();
let (rtc_engine, join_response, engine_events) = RtcEngine::connect(
url,
token,
Expand Down