diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 022e39106..b6d689602 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "9a241194a05459dda7f4c65786ed4ee920464ebcd778b6388ef33fdb661c390a", + "checksum": "3617ba629cc3c6bf6b4df0b7596a6285147b1f712bf925e4ffd13e4f59dc3d4b", "crates": { "addr2line 0.20.0": { "name": "addr2line", @@ -2130,6 +2130,10 @@ { "id": "thiserror 1.0.50", "target": "thiserror" + }, + { + "id": "zerocopy 0.7.34", + "target": "zerocopy" } ], "selects": {} diff --git a/Cargo.lock b/Cargo.lock index d06e728db..0bd8399cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -355,6 +355,7 @@ dependencies = [ "static_assertions", "system_api", "thiserror", + "zerocopy", ] [[package]] diff --git a/cras/common/rust_common.h b/cras/common/rust_common.h index 7e8b4a9f3..16e15f667 100644 --- a/cras/common/rust_common.h +++ b/cras/common/rust_common.h @@ -18,19 +18,6 @@ extern "C" { #include #include -#define NUM_CRAS_DLCS 3 - -#define CRAS_DLC_ID_STRING_MAX_LENGTH 50 - -/** - * All supported DLCs in CRAS. - */ -enum CrasDlcId { - CrasDlcSrBt, - CrasDlcNcAp, - CrasDlcIntelligoBeamforming, -}; - enum CRAS_FRA_SIGNAL { PeripheralsUsbSoundCard = 0, USBAudioConfigureFailed, diff --git a/cras/common/src/types_internal.rs b/cras/common/src/types_internal.rs index 294551e79..f548afb17 100644 --- a/cras/common/src/types_internal.rs +++ b/cras/common/src/types_internal.rs @@ -5,9 +5,7 @@ use std::borrow::Cow; use std::ffi::CStr; use std::ffi::CString; -use std::fmt::Display; -use anyhow::bail; use bitflags::bitflags; use itertools::Itertools; use serde::Serialize; @@ -184,59 +182,8 @@ pub struct CrasEffectUIAppearance { pub show_effect_fallback_message: bool, } -/// All supported DLCs in CRAS. -#[repr(C)] -#[derive(Clone, Copy, PartialEq, Hash, Eq, Debug)] -pub enum CrasDlcId { - CrasDlcSrBt, - CrasDlcNcAp, - CrasDlcIntelligoBeamforming, -} - -// The list of DLCs that are installed automatically. -pub const MANAGED_DLCS: &[CrasDlcId] = &[ - CrasDlcId::CrasDlcSrBt, - CrasDlcId::CrasDlcNcAp, - CrasDlcId::CrasDlcIntelligoBeamforming, -]; - -pub const NUM_CRAS_DLCS: usize = 3; -// Assert that NUM_CRAS_DLCS is updated. -// We cannot assign MANAGED_DLCS.len() to NUM_CRAS_DLCS because cbindgen does -// not seem to understand it. -static_assertions::const_assert_eq!(NUM_CRAS_DLCS, MANAGED_DLCS.len()); - -pub const CRAS_DLC_ID_STRING_MAX_LENGTH: i32 = 50; -impl CrasDlcId { - pub fn as_str(&self) -> &'static str { - match self { - // The length of these strings should be bounded by - // CRAS_DLC_ID_STRING_MAX_LENGTH - CrasDlcId::CrasDlcSrBt => "sr-bt-dlc", - CrasDlcId::CrasDlcNcAp => "nc-ap-dlc", - CrasDlcId::CrasDlcIntelligoBeamforming => "intelligo-beamforming-dlc", - } - } -} - -impl TryFrom<&str> for CrasDlcId { - type Error = anyhow::Error; - - fn try_from(value: &str) -> anyhow::Result { - for dlc in MANAGED_DLCS { - if dlc.as_str() == value { - return Ok(dlc.clone()); - } - } - bail!("unknown DLC {value}"); - } -} - -impl Display for CrasDlcId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.as_str()) - } -} +pub const SR_BT_DLC: &str = "sr-bt-dlc"; +pub const NC_AP_DLC: &str = "nc-ap-dlc"; #[cfg(test)] mod tests { diff --git a/cras/server/platform/dlc/Cargo.toml b/cras/server/platform/dlc/Cargo.toml index dd8d79c2c..e6812f544 100644 --- a/cras/server/platform/dlc/Cargo.toml +++ b/cras/server/platform/dlc/Cargo.toml @@ -16,6 +16,7 @@ protobuf = { workspace = true } static_assertions = { workspace = true } system_api = { workspace = true, optional = true } thiserror = { workspace = true } +zerocopy = { workspace = true } [features] dlc = ["system_api"] diff --git a/cras/server/platform/dlc/dlc.h b/cras/server/platform/dlc/dlc.h index c07c427ed..8e2789eff 100644 --- a/cras/server/platform/dlc/dlc.h +++ b/cras/server/platform/dlc/dlc.h @@ -19,25 +19,30 @@ extern "C" { #include #include "cras/common/rust_common.h" -struct CrasDlcDownloadConfig { - bool dlcs_to_download[NUM_CRAS_DLCS]; +/** + * This type exists as an alternative to heap-allocated C-strings. + * + * This type, as a simple value, is free of ownership or memory leak issues, + * when we pass this in a callback we don't have to worry about who should free the string. + */ +struct CrasDlcId128 { + char id[128]; }; -typedef int (*DlcInstallOnSuccessCallback)(enum CrasDlcId, int32_t); +typedef int (*DlcInstallOnSuccessCallback)(struct CrasDlcId128 id, int32_t elapsed_seconds); -typedef int (*DlcInstallOnFailureCallback)(enum CrasDlcId, int32_t); +typedef int (*DlcInstallOnFailureCallback)(struct CrasDlcId128 id, int32_t elapsed_seconds); /** - * Returns `true` if the DLC package is ready for use, otherwise - * returns `false`. + * Returns `true` if sr-bt-dlc is available. */ -bool cras_dlc_is_available(enum CrasDlcId id); +bool cras_dlc_is_sr_bt_available(void); /** - * Returns the root path of the DLC package. + * Returns the root path of sr-bt-dlc. * The returned string should be freed with cras_rust_free_string. */ -char *cras_dlc_get_root_path(enum CrasDlcId id); +char *cras_dlc_get_sr_bt_root_path(void); /** * Overrides the DLC state for DLC `id`. @@ -45,7 +50,7 @@ char *cras_dlc_get_root_path(enum CrasDlcId id); * # Safety * root_path must be a valid NULL terminated UTF-8 string. */ -void cras_dlc_override_state_for_testing(enum CrasDlcId id, bool installed, const char *root_path); +void cras_dlc_override_sr_bt_for_testing(bool installed, const char *root_path); /** * Reset all DLC overrides. @@ -55,8 +60,7 @@ void cras_dlc_reset_overrides_for_testing(void); /** * Start a thread to download all DLCs. */ -void download_dlcs_until_installed_with_thread(struct CrasDlcDownloadConfig download_config, - DlcInstallOnSuccessCallback dlc_install_on_success_callback, +void download_dlcs_until_installed_with_thread(DlcInstallOnSuccessCallback dlc_install_on_success_callback, DlcInstallOnFailureCallback dlc_install_on_failure_callback); #endif /* CRAS_SERVER_PLATFORM_DLC_DLC_H_ */ diff --git a/cras/server/platform/dlc/src/bindings.rs b/cras/server/platform/dlc/src/bindings.rs index c2fa4c566..da2bbd43c 100644 --- a/cras/server/platform/dlc/src/bindings.rs +++ b/cras/server/platform/dlc/src/bindings.rs @@ -8,31 +8,30 @@ use std::ffi::CString; use std::ptr; use std::thread; +use cras_common::types_internal::SR_BT_DLC; + use super::get_dlc_state_cached; -use super::CrasDlcId; use super::Result; -use crate::download_dlcs_init; use crate::download_dlcs_until_installed; use crate::DlcInstallOnFailureCallback; use crate::DlcInstallOnSuccessCallback; -fn get_dlc_root_path(id: CrasDlcId) -> Result { +fn get_dlc_root_path(id: &str) -> Result { let dlc_state = get_dlc_state_cached(id); CString::new(dlc_state.root_path).map_err(|e| e.into()) } -/// Returns `true` if the DLC package is ready for use, otherwise -/// returns `false`. +/// Returns `true` if sr-bt-dlc is available. #[no_mangle] -pub extern "C" fn cras_dlc_is_available(id: CrasDlcId) -> bool { - get_dlc_state_cached(id).installed +pub extern "C" fn cras_dlc_is_sr_bt_available() -> bool { + get_dlc_state_cached(SR_BT_DLC).installed } -/// Returns the root path of the DLC package. +/// Returns the root path of sr-bt-dlc. /// The returned string should be freed with cras_rust_free_string. #[no_mangle] -pub extern "C" fn cras_dlc_get_root_path(id: CrasDlcId) -> *mut c_char { - match get_dlc_root_path(id) { +pub extern "C" fn cras_dlc_get_sr_bt_root_path() -> *mut c_char { + match get_dlc_root_path(SR_BT_DLC) { Ok(root_path) => root_path.into_raw(), Err(_) => ptr::null_mut(), } @@ -43,8 +42,7 @@ pub extern "C" fn cras_dlc_get_root_path(id: CrasDlcId) -> *mut c_char { /// # Safety /// root_path must be a valid NULL terminated UTF-8 string. #[no_mangle] -pub unsafe extern "C" fn cras_dlc_override_state_for_testing( - id: CrasDlcId, +pub unsafe extern "C" fn cras_dlc_override_sr_bt_for_testing( installed: bool, root_path: *const c_char, ) { @@ -57,7 +55,7 @@ pub unsafe extern "C" fn cras_dlc_override_state_for_testing( .into() }; crate::override_state_for_testing( - id, + SR_BT_DLC, crate::State { installed, root_path, @@ -74,17 +72,13 @@ pub extern "C" fn cras_dlc_reset_overrides_for_testing() { /// Start a thread to download all DLCs. #[no_mangle] pub extern "C" fn download_dlcs_until_installed_with_thread( - download_config: super::CrasDlcDownloadConfig, dlc_install_on_success_callback: DlcInstallOnSuccessCallback, dlc_install_on_failure_callback: DlcInstallOnFailureCallback, ) { - download_dlcs_init(&download_config); - thread::Builder::new() .name("cras-dlc".into()) .spawn(move || { download_dlcs_until_installed( - download_config, dlc_install_on_success_callback, dlc_install_on_failure_callback, ) diff --git a/cras/server/platform/dlc/src/chromiumos.rs b/cras/server/platform/dlc/src/chromiumos.rs index 69c30f958..c35ee5fcb 100644 --- a/cras/server/platform/dlc/src/chromiumos.rs +++ b/cras/server/platform/dlc/src/chromiumos.rs @@ -12,7 +12,6 @@ use system_api::dlcservice::dlc_state::State; use system_api::dlcservice::DlcState; use system_api::dlcservice::InstallRequest; -use super::CrasDlcId; use super::Result; const DBUS_TIMEOUT: Duration = Duration::from_millis(500); @@ -34,7 +33,7 @@ impl super::ServiceTrait for Service { Ok(Self) } - fn install(&mut self, id: CrasDlcId) -> Result<()> { + fn install(&mut self, id: &str) -> Result<()> { let connection = Connection::new_system()?; let conn_path = get_dlcservice_connection_path(&connection); @@ -44,11 +43,11 @@ impl super::ServiceTrait for Service { Ok(conn_path.install(request.write_to_bytes()?)?) } - fn get_dlc_state(&mut self, id: CrasDlcId) -> Result { + fn get_dlc_state(&mut self, id: &str) -> Result { let connection = Connection::new_system()?; let conn_path = get_dlcservice_connection_path(&connection); - let res = conn_path.get_dlc_state(id.as_str())?; + let res = conn_path.get_dlc_state(id)?; let mut dlc_state = DlcState::new(); dlc_state.merge_from_bytes(&res)?; Ok(crate::State { diff --git a/cras/server/platform/dlc/src/lib.rs b/cras/server/platform/dlc/src/lib.rs index 2062142da..77bfd31b0 100644 --- a/cras/server/platform/dlc/src/lib.rs +++ b/cras/server/platform/dlc/src/lib.rs @@ -12,9 +12,10 @@ use std::sync::Mutex; use std::thread::sleep; use std::time; -use cras_common::types_internal::CrasDlcId; +use cras_s2::global::cras_s2_get_dlcs_to_install; use once_cell::sync::Lazy; use thiserror::Error; +use zerocopy::AsBytes; #[derive(Clone)] pub struct State { @@ -42,8 +43,8 @@ pub type Result = std::result::Result; trait ServiceTrait: Sized { fn new() -> Result; - fn install(&mut self, id: CrasDlcId) -> Result<()>; - fn get_dlc_state(&mut self, id: CrasDlcId) -> Result; + fn install(&mut self, id: &str) -> Result<()>; + fn get_dlc_state(&mut self, id: &str) -> Result; } #[cfg(feature = "dlc")] @@ -51,13 +52,13 @@ type Service = chromiumos::Service; #[cfg(not(feature = "dlc"))] type Service = stub::Service; -static STATE_OVERRIDES: Lazy>> = +static STATE_OVERRIDES: Lazy>> = Lazy::new(|| Mutex::new(Default::default())); -static STATE_CACHE: Lazy>> = +static STATE_CACHE: Lazy>> = Lazy::new(|| Mutex::new(Default::default())); -pub fn install_dlc(id: CrasDlcId) -> Result { +pub fn install_dlc(id: &str) -> Result { let mut service = Service::new()?; service.install(id)?; let state = service.get_dlc_state(id)?; @@ -67,16 +68,16 @@ pub fn install_dlc(id: CrasDlcId) -> Result { Ok(state) } -pub fn get_dlc_state_cached(id: CrasDlcId) -> State { +pub fn get_dlc_state_cached(id: &str) -> State { // Return override if exist. - if let Some(state) = STATE_OVERRIDES.lock().unwrap().get(&id) { + if let Some(state) = STATE_OVERRIDES.lock().unwrap().get(id) { return state.clone(); } STATE_CACHE .lock() .unwrap() - .get(&id) + .get(id) .cloned() .unwrap_or_else(|| State { installed: false, @@ -84,48 +85,49 @@ pub fn get_dlc_state_cached(id: CrasDlcId) -> State { }) } -fn override_state_for_testing(id: CrasDlcId, state: State) { - STATE_OVERRIDES.lock().unwrap().insert(id, state); +fn override_state_for_testing(id: &str, state: State) { + STATE_OVERRIDES + .lock() + .unwrap() + .insert(id.to_string(), state); } fn reset_overrides() { STATE_OVERRIDES.lock().unwrap().clear(); } -// Called when a dlc is installed successfully, with the following arguments: -// - CrasDlcId: the id of the installed dlc. -// - i32: the number of retried times. -type DlcInstallOnSuccessCallback = extern "C" fn(CrasDlcId, i32) -> libc::c_int; - -// Called when a dlc failed to install, with the following arguments: -// - CrasDlcId: the id of the installed dlc. -// - i32: the elapsed time when the installation failure occurs. -type DlcInstallOnFailureCallback = extern "C" fn(CrasDlcId, i32) -> libc::c_int; - +/// This type exists as an alternative to heap-allocated C-strings. +/// +/// This type, as a simple value, is free of ownership or memory leak issues, +/// when we pass this in a callback we don't have to worry about who should free the string. #[repr(C)] -pub struct CrasDlcDownloadConfig { - pub dlcs_to_download: [bool; cras_common::types_internal::NUM_CRAS_DLCS], +pub struct CrasDlcId128 { + id: [libc::c_char; 128], } -fn get_dlc_ids_to_download(download_config: &CrasDlcDownloadConfig) -> Vec<&CrasDlcId> { - download_config - .dlcs_to_download - .iter() - .zip(cras_common::types_internal::MANAGED_DLCS.iter()) - .filter_map(|(download, id)| if *download { Some(id) } else { None }) - .collect() +impl From<&str> for CrasDlcId128 { + fn from(value: &str) -> Self { + let b = value.as_bytes(); + let to_copy = b.len().min(127); + let mut id = [0; 128]; + id.as_bytes_mut()[..to_copy].clone_from_slice(&b[..to_copy]); + Self { id } + } } -fn download_dlcs_init(download_config: &CrasDlcDownloadConfig) { - cras_s2::global::cras_s2_init_dlc_installed(HashMap::from_iter( - get_dlc_ids_to_download(download_config) - .into_iter() - .map(|&dlc| (dlc, false)), - )) -} +// Called when a dlc is installed successfully, with the following arguments: +// - id: the id of the installed dlc. +// - elapsed_seconds: the elapsed time when the installation succeeded. +type DlcInstallOnSuccessCallback = + extern "C" fn(id: CrasDlcId128, elapsed_seconds: i32) -> libc::c_int; + +// Called when a dlc failed to install, with the following arguments: +// - id: the id of the installed dlc. +// - elapsed_seconds: the elapsed time when the installation failed. +type DlcInstallOnFailureCallback = + extern "C" fn(id: CrasDlcId128, elapsed_seconds: i32) -> libc::c_int; fn download_dlcs_until_installed( - download_config: CrasDlcDownloadConfig, dlc_install_on_success_callback: DlcInstallOnSuccessCallback, dlc_install_on_failure_callback: DlcInstallOnFailureCallback, ) { @@ -133,21 +135,27 @@ fn download_dlcs_until_installed( let mut retry_sleep = time::Duration::from_secs(1); let max_retry_sleep = time::Duration::from_secs(120); - let mut todo = get_dlc_ids_to_download(&download_config); + let mut todo = cras_s2_get_dlcs_to_install(); for _retry_count in 0..i32::MAX { let mut todo_next = vec![]; - for &dlc in todo.iter() { - match install_dlc(*dlc) { + for dlc in todo.iter() { + match install_dlc(dlc) { Ok(state) => { log::info!("successfully installed {dlc}"); - STATE_CACHE.lock().unwrap().insert(*dlc, state); - cras_s2::global::cras_s2_set_dlc_installed(*dlc, true); - dlc_install_on_success_callback(*dlc, start_time.elapsed().as_secs() as i32); + STATE_CACHE.lock().unwrap().insert(dlc.to_string(), state); + cras_s2::global::cras_s2_set_dlc_installed(dlc, true); + dlc_install_on_success_callback( + CrasDlcId128::from(dlc.as_str()), + start_time.elapsed().as_secs() as i32, + ); } Err(e) => { log::info!("failed to install {dlc}: {e}"); - todo_next.push(dlc); - dlc_install_on_failure_callback(*dlc, start_time.elapsed().as_secs() as i32); + todo_next.push(dlc.to_string()); + dlc_install_on_failure_callback( + CrasDlcId128::from(dlc.as_str()), + start_time.elapsed().as_secs() as i32, + ); } } } diff --git a/cras/server/platform/dlc/src/stub.rs b/cras/server/platform/dlc/src/stub.rs index cf3ed6a16..6d6725c40 100644 --- a/cras/server/platform/dlc/src/stub.rs +++ b/cras/server/platform/dlc/src/stub.rs @@ -12,11 +12,11 @@ impl super::ServiceTrait for Service { Ok(Self) } - fn install(&mut self, _id: super::CrasDlcId) -> Result<()> { + fn install(&mut self, _id: &str) -> Result<()> { Err(super::Error::Unsupported) } - fn get_dlc_state(&mut self, _id: super::CrasDlcId) -> Result { + fn get_dlc_state(&mut self, _id: &str) -> Result { Ok(super::State { installed: false, root_path: String::new(), diff --git a/cras/server/processor/src/lib.rs b/cras/server/processor/src/lib.rs index 8b4d40c95..70e282ec0 100644 --- a/cras/server/processor/src/lib.rs +++ b/cras/server/processor/src/lib.rs @@ -24,7 +24,6 @@ use audio_processor::processors::ThreadedProcessor; use audio_processor::AudioProcessor; use audio_processor::Format; use audio_processor::ProcessorVec; -use cras_common::types_internal::CrasDlcId; use cras_common::types_internal::CrasProcessorEffect; use cras_dlc::get_dlc_state_cached; use cras_s2::global::cras_s2_get_beamforming_config_path; @@ -95,9 +94,8 @@ impl audio_processor::cdcfg::ResolverContext for CrasProcessorResolverContext { } fn get_dlc_root_path(&self, dlc_id: &str) -> anyhow::Result { - let cras_dlc_id = CrasDlcId::try_from(dlc_id)?; - let dlc_state = get_dlc_state_cached(cras_dlc_id); - ensure!(dlc_state.installed, "{cras_dlc_id} not installed"); + let dlc_state = get_dlc_state_cached(dlc_id); + ensure!(dlc_state.installed, "{dlc_id} not installed"); Ok(dlc_state.root_path.into()) } diff --git a/cras/server/s2/s2.h b/cras/server/s2/s2.h index 1e9ce456f..124549206 100644 --- a/cras/server/s2/s2.h +++ b/cras/server/s2/s2.h @@ -35,7 +35,12 @@ void cras_s2_set_reset_iodev_list_for_voice_isolation(ResetIodevListForVoiceIsol char *cras_s2_get_audio_effect_dlcs(void); -void cras_s2_set_dlc_installed(enum CrasDlcId dlc, bool installed); +/** + * # Safety + * + * dlc must be a NULL terminated string. + */ +void cras_s2_set_dlc_installed_for_test(const char *dlc, bool installed); bool cras_s2_get_ap_nc_allowed(void); diff --git a/cras/server/s2/src/global.rs b/cras/server/s2/src/global.rs index aba749309..a5536df85 100644 --- a/cras/server/s2/src/global.rs +++ b/cras/server/s2/src/global.rs @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::collections::HashMap; use std::ffi::c_char; +use std::ffi::CStr; use std::ffi::CString; use std::ops::Deref; use std::path::PathBuf; @@ -11,7 +11,6 @@ use std::sync::Mutex; use std::sync::MutexGuard; use std::sync::OnceLock; -use cras_common::types_internal::CrasDlcId; use cras_common::types_internal::CrasEffectUIAppearance; use cras_common::types_internal::CrasProcessorEffect; use cras_common::types_internal::CRAS_NC_PROVIDER; @@ -69,30 +68,38 @@ pub extern "C" fn cras_s2_set_reset_iodev_list_for_voice_isolation( state().set_reset_iodev_list_for_voice_isolation(reset_iodev_list_for_voice_isolation); } -pub fn cras_s2_init_dlc_installed(dlc_installed: HashMap) { - state().init_dlc_installed(dlc_installed); -} - #[no_mangle] pub extern "C" fn cras_s2_get_audio_effect_dlcs() -> *mut c_char { // TODO(b/372393426): Consider returning protobuf instead of string. let s = state() .input - .dlc_installed - .as_ref() - .unwrap_or(&HashMap::new()) - .keys() + .dlcs_to_install_cached + .iter() .cloned() .collect::>() .join(","); CString::new(s).expect("CString::new").into_raw() } -#[no_mangle] -pub extern "C" fn cras_s2_set_dlc_installed(dlc: CrasDlcId, installed: bool) { +pub fn cras_s2_get_dlcs_to_install() -> Vec { + state().input.dlcs_to_install_cached.clone() +} + +pub fn cras_s2_set_dlc_installed(dlc: &str, installed: bool) { state().set_dlc_installed(dlc, installed); } +/// # Safety +/// +/// dlc must be a NULL terminated string. +#[no_mangle] +pub unsafe extern "C" fn cras_s2_set_dlc_installed_for_test( + dlc: *const libc::c_char, + installed: bool, +) { + cras_s2_set_dlc_installed(CStr::from_ptr(dlc).to_str().unwrap(), installed); +} + #[no_mangle] pub extern "C" fn cras_s2_get_ap_nc_allowed() -> bool { state().output.get_ap_nc_status().allowed @@ -147,6 +154,8 @@ pub unsafe extern "C" fn cras_s2_init( } } s.set_feature_tier(CrasFeatureTier::new_c(board_name, cpu_name)); + s.input.dlcs_to_install_cached = s.compute_dlcs_to_install(); + s.update(); } #[no_mangle] diff --git a/cras/server/s2/src/lib.rs b/cras/server/s2/src/lib.rs index 0755dbbff..8b630fb89 100644 --- a/cras/server/s2/src/lib.rs +++ b/cras/server/s2/src/lib.rs @@ -3,12 +3,14 @@ // found in the LICENSE file. use std::collections::HashMap; +use std::collections::HashSet; -use cras_common::types_internal::CrasDlcId; use cras_common::types_internal::CrasEffectUIAppearance; use cras_common::types_internal::CRAS_NC_PROVIDER; use cras_common::types_internal::CRAS_NC_PROVIDER_PREFERENCE_ORDER; use cras_common::types_internal::EFFECT_TYPE; +use cras_common::types_internal::NC_AP_DLC; +use cras_common::types_internal::SR_BT_DLC; use cras_feature_tier::CrasFeatureTier; use global::ResetIodevListForVoiceIsolation; use processing::BeamformingConfig; @@ -27,7 +29,9 @@ struct Input { /// Tells whether the DLC manager is ready. /// Used by tests to avoid races. dlc_manager_ready: bool, - dlc_installed: Option>, + /// Cached result of compute_dlcs_to_install. + dlcs_to_install_cached: Vec, + dlcs_installed: HashSet, style_transfer_featured_allowed: bool, // cros_config /audio/main cras-config-dir. cras_config_dir: String, @@ -92,18 +96,11 @@ fn resolve(input: &Input) -> Output { let beamforming_supported = matches!(input.beamforming_config, BeamformingConfig::Supported(_)); let beamforming_allowed = match &input.beamforming_config { BeamformingConfig::Unsupported { .. } => false, - BeamformingConfig::Supported(properties) => properties.required_dlcs.iter().all(|dlc| { - input - .dlc_installed - .as_ref() - .is_some_and(|d| d.get(dlc).cloned().unwrap_or(false)) - }), + BeamformingConfig::Supported(properties) => { + properties.required_dlcs.is_subset(&input.dlcs_installed) + } }; - let dlc_nc_ap_installed = input.dlc_installed.as_ref().is_some_and(|d| { - d.get(CrasDlcId::CrasDlcNcAp.as_str()) - .cloned() - .unwrap_or(false) - }); + let dlc_nc_ap_installed = input.dlcs_installed.contains(NC_AP_DLC); let dsp_input_effects_blocked = if input.bypass_block_dsp_nc { false } else if input.nc_standalone_mode { @@ -205,9 +202,9 @@ fn resolve(input: &Input) -> Output { Output { audio_effects_ready: input - .dlc_installed - .as_ref() - .is_some_and(|d| d.values().all(|&installed| installed)), + .dlcs_to_install_cached + .iter() + .all(|dlc| input.dlcs_installed.contains(dlc)), dsp_input_effects_blocked, audio_effects_status, audio_effect_ui_appearance, @@ -321,6 +318,20 @@ impl S2 { } } + fn compute_dlcs_to_install(&self) -> Vec { + let mut out = Vec::new(); + if self.input.feature_tier.sr_bt_supported { + out.push(SR_BT_DLC.to_string()); + } + if self.output.get_ap_nc_status().supported { + out.push(NC_AP_DLC.to_string()); + } + if let BeamformingConfig::Supported(properties) = &self.input.beamforming_config { + out.extend(properties.required_dlcs.iter().cloned()); + } + out + } + fn set_feature_tier(&mut self, feature_tier: CrasFeatureTier) { self.input.feature_tier = feature_tier; self.update(); @@ -341,20 +352,11 @@ impl S2 { self.update(); } - fn init_dlc_installed(&mut self, dlc_installed: HashMap) { - self.input.dlc_installed = - Some(HashMap::from_iter(dlc_installed.into_iter().map( - |(dlc, installed)| (dlc.as_str().to_string(), installed), - ))); - self.update(); - } - - fn set_dlc_installed(&mut self, dlc: CrasDlcId, installed: bool) { - if self.input.dlc_installed.is_none() { - self.init_dlc_installed(Default::default()); - } - if let Some(ref mut dlc_installed) = self.input.dlc_installed { - dlc_installed.insert(dlc.as_str().to_string(), installed); + fn set_dlc_installed(&mut self, dlc: &str, installed: bool) { + if installed { + self.input.dlcs_installed.insert(dlc.to_string()); + } else { + self.input.dlcs_installed.remove(dlc); } self.update(); } @@ -515,10 +517,10 @@ mod tests { use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering; - use cras_common::types_internal::CrasDlcId; use cras_common::types_internal::CrasEffectUIAppearance; use cras_common::types_internal::CRAS_NC_PROVIDER; use cras_common::types_internal::EFFECT_TYPE; + use cras_common::types_internal::NC_AP_DLC; use crate::processing::BeamformingConfig; use crate::processing::BeamformingProperties; @@ -526,6 +528,8 @@ mod tests { use crate::AudioEffectStatus; use crate::S2; + const BF_DLC: &str = "bf-dlc-for-test"; + #[test] fn test_ap_nc() { let mut s = S2::new(); @@ -542,7 +546,7 @@ mod tests { s.input.feature_tier.ap_nc_supported = true; assert_eq!(s.output.get_ap_nc_status().allowed, false); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); s.set_ap_nc_featured_allowed(true); assert_eq!(s.output.get_ap_nc_status().allowed, true); @@ -573,7 +577,7 @@ mod tests { s.set_style_transfer_featured_allowed(true); assert_eq!(s.output.get_ast_status().allowed, false); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); assert_eq!(s.output.get_ast_status().allowed, true); s.set_style_transfer_featured_allowed(false); @@ -598,9 +602,7 @@ mod tests { s.set_ap_nc_segmentation_allowed(true); s.set_style_transfer_featured_allowed(true); s.set_beamforming_config(BeamformingConfig::Supported(BeamformingProperties { - required_dlcs: HashSet::from([CrasDlcId::CrasDlcIntelligoBeamforming - .as_str() - .to_string()]), + required_dlcs: HashSet::from([BF_DLC.to_string()]), ..Default::default() })); assert!(s.output.get_bf_status().supported); @@ -611,7 +613,7 @@ mod tests { assert!(s.output.get_bf_status().supported); assert!(!s.output.get_bf_status().allowed); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); + s.set_dlc_installed(BF_DLC, true); assert!(s.output.get_bf_status().allowed); let dlcs = HashSet::from(["does-not-exist".to_string()]); @@ -630,55 +632,31 @@ mod tests { #[test] fn test_dlc() { let mut s = S2::new(); - assert!(s.input.dlc_installed.is_none()); + assert!(s.input.dlcs_installed.is_empty()); assert!(!s.input.dlc_manager_ready); s.set_dlc_manager_ready(); assert!(s.input.dlc_manager_ready); - s.init_dlc_installed(HashMap::from([ - (CrasDlcId::CrasDlcNcAp, false), - (CrasDlcId::CrasDlcIntelligoBeamforming, false), - ])); - assert_eq!( - s.input.dlc_installed.as_ref().unwrap_or(&HashMap::new()), - &HashMap::from([ - (CrasDlcId::CrasDlcNcAp.as_str().to_string(), false), - ( - CrasDlcId::CrasDlcIntelligoBeamforming.as_str().to_string(), - false - ) - ]) - ); - - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); assert_eq!( - s.input.dlc_installed.as_ref().unwrap_or(&HashMap::new()), - &HashMap::from([ - (CrasDlcId::CrasDlcNcAp.as_str().to_string(), true), - ( - CrasDlcId::CrasDlcIntelligoBeamforming.as_str().to_string(), - false - ) - ]) + s.input.dlcs_installed, + HashSet::from([NC_AP_DLC.to_string()]) ); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); - assert_eq!( - s.input.dlc_installed.as_ref().unwrap_or(&HashMap::new()), - &HashMap::from([ - (CrasDlcId::CrasDlcNcAp.as_str().to_string(), true), - ( - CrasDlcId::CrasDlcIntelligoBeamforming.as_str().to_string(), - true - ) - ]) - ); + s.set_dlc_installed(NC_AP_DLC, false); + assert_eq!(s.input.dlcs_installed, HashSet::new()); } #[test] fn test_audio_effects_ready() { let mut s = S2::new(); - assert!(!s.output.audio_effects_ready); + s.input.dlcs_to_install_cached = vec![NC_AP_DLC.to_string(), BF_DLC.to_string()]; + s.update(); + assert!( + !s.output.audio_effects_ready, + "{}", + serde_json::to_string_pretty(&s).unwrap() + ); // Simply verifies the callback is called. static CALLED: AtomicBool = AtomicBool::new(false); @@ -702,18 +680,14 @@ mod tests { assert!(!CALLED.load(Ordering::SeqCst)); assert!(!s.output.audio_effects_ready); - s.init_dlc_installed(HashMap::from([ - (CrasDlcId::CrasDlcNcAp, false), - (CrasDlcId::CrasDlcIntelligoBeamforming, false), - ])); assert!(!s.output.audio_effects_ready); assert!(!CALLED.load(Ordering::SeqCst)); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); assert!(!s.output.audio_effects_ready); assert!(!CALLED.load(Ordering::SeqCst)); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); + s.set_dlc_installed(BF_DLC, true); assert!(s.output.audio_effects_ready); assert!(CALLED.load(Ordering::SeqCst)); assert_eq!( @@ -735,7 +709,7 @@ mod tests { ); CALLED.store(false, Ordering::SeqCst); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, false); + s.set_dlc_installed(NC_AP_DLC, false); assert!(!s.output.audio_effects_ready); assert!(CALLED.load(Ordering::SeqCst)); assert_eq!( @@ -864,7 +838,6 @@ mod tests { #[test] fn test_show_effect_fallback_message() { let mut s = S2::new(); - s.init_dlc_installed(Default::default()); assert_eq!( s.output .audio_effect_ui_appearance @@ -873,7 +846,7 @@ mod tests { ); s.set_ap_nc_featured_allowed(true); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); s.set_ap_nc_segmentation_allowed(true); s.set_style_transfer_featured_allowed(true); s.set_active_input_node_compatible_nc_providers(CRAS_NC_PROVIDER::all()); @@ -907,7 +880,7 @@ mod tests { assert_eq!(s.output.system_valid_nc_providers, expected); s.set_ap_nc_featured_allowed(true); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); expected |= CRAS_NC_PROVIDER::AP; assert_eq!(s.output.system_valid_nc_providers, expected); @@ -917,12 +890,10 @@ mod tests { assert_eq!(s.output.system_valid_nc_providers, expected); s.set_beamforming_config(BeamformingConfig::Supported(BeamformingProperties { - required_dlcs: HashSet::from([CrasDlcId::CrasDlcIntelligoBeamforming - .as_str() - .to_string()]), + required_dlcs: HashSet::from([BF_DLC.to_string()]), ..Default::default() })); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); + s.set_dlc_installed(BF_DLC, true); s.set_voice_isolation_ui_preferred_effect(EFFECT_TYPE::STYLE_TRANSFER); assert_eq!(s.output.system_valid_nc_providers, expected); @@ -939,7 +910,7 @@ mod tests { // Set DSP and AP NC supported and allowed. s.set_dsp_nc_supported(true); s.set_ap_nc_featured_allowed(true); - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); // DSP NC priority is higher than AP NC. assert_eq!( s.resolve_nc_provider(CRAS_NC_PROVIDER::all(), true), @@ -993,12 +964,10 @@ mod tests { // Test for UI preferred effect s.set_beamforming_config(BeamformingConfig::Supported(BeamformingProperties { - required_dlcs: HashSet::from([CrasDlcId::CrasDlcIntelligoBeamforming - .as_str() - .to_string()]), + required_dlcs: HashSet::from([BF_DLC.to_string()]), ..Default::default() })); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); + s.set_dlc_installed(BF_DLC, true); s.set_voice_isolation_ui_preferred_effect(EFFECT_TYPE::STYLE_TRANSFER); assert_eq!( s.resolve_nc_provider(CRAS_NC_PROVIDER::all(), true), @@ -1028,19 +997,17 @@ mod tests { assert!(!CALLED.load(Ordering::SeqCst)); // Install the DLC should set AST and AP NC allowed. - s.set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + s.set_dlc_installed(NC_AP_DLC, true); assert!(CALLED.load(Ordering::SeqCst)); CALLED.store(false, Ordering::SeqCst); s.set_voice_isolation_ui_preferred_effect(EFFECT_TYPE::STYLE_TRANSFER); // Set BF as supported and allowed. s.set_beamforming_config(BeamformingConfig::Supported(BeamformingProperties { - required_dlcs: HashSet::from([CrasDlcId::CrasDlcIntelligoBeamforming - .as_str() - .to_string()]), + required_dlcs: HashSet::from([BF_DLC.to_string()]), ..Default::default() })); - s.set_dlc_installed(CrasDlcId::CrasDlcIntelligoBeamforming, true); + s.set_dlc_installed(BF_DLC, true); // No need to reset iodev list because the preferred effect is AST. assert!(!CALLED.load(Ordering::SeqCst)); diff --git a/cras/src/server/cras_dlc_manager.c b/cras/src/server/cras_dlc_manager.c index 5ed6d0cc6..caa5e3e0b 100644 --- a/cras/src/server/cras_dlc_manager.c +++ b/cras/src/server/cras_dlc_manager.c @@ -9,7 +9,7 @@ #include "cras/src/server/cras_iodev_list.h" #include "cras/src/server/cras_server_metrics.h" -static int32_t dlc_install_on_success_callback(enum CrasDlcId dlc_id, +static int32_t dlc_install_on_success_callback(struct CrasDlcId128 dlc_id, int32_t elapsed_seconds) { const int ret = cras_server_metrics_dlc_install_elapsed_time_on_success( dlc_id, elapsed_seconds); @@ -28,16 +28,16 @@ static void notify_dlc_install_success() { cras_iodev_list_notify_nodes_changed(); } -static int32_t dlc_install_on_failure_callback(enum CrasDlcId dlc_id, +static int32_t dlc_install_on_failure_callback(struct CrasDlcId128 dlc_id, int32_t elapsed_seconds) { return cras_server_metrics_dlc_install_elapsed_time_on_failure( dlc_id, elapsed_seconds); } -void cras_dlc_manager_init(struct CrasDlcDownloadConfig dl_cfg) { +void cras_dlc_manager_init() { cras_main_message_add_handler(CRAS_MAIN_DLC_INSTALLED, notify_dlc_install_success, NULL); - download_dlcs_until_installed_with_thread( - dl_cfg, dlc_install_on_success_callback, dlc_install_on_failure_callback); + download_dlcs_until_installed_with_thread(dlc_install_on_success_callback, + dlc_install_on_failure_callback); } diff --git a/cras/src/server/cras_dlc_manager.h b/cras/src/server/cras_dlc_manager.h index 7b451dcb8..95a2ca98d 100644 --- a/cras/src/server/cras_dlc_manager.h +++ b/cras/src/server/cras_dlc_manager.h @@ -11,7 +11,7 @@ extern "C" { #endif -void cras_dlc_manager_init(struct CrasDlcDownloadConfig dl_cfg); +void cras_dlc_manager_init(); #ifdef __cplusplus } // extern "C" diff --git a/cras/src/server/cras_server.c b/cras/src/server/cras_server.c index 46b572c74..95598fbb5 100644 --- a/cras/src/server/cras_server.c +++ b/cras/src/server/cras_server.c @@ -577,15 +577,7 @@ int cras_server_run(unsigned int profile_disable_mask) { // `cras_dlc_manager` writes information that can be queried by dbus call, so // we initialize it before initializing dbus threads. - cras_dlc_manager_init((struct CrasDlcDownloadConfig){ - .dlcs_to_download = - { - [CrasDlcSrBt] = cras_system_get_sr_bt_supported(), - [CrasDlcNcAp] = true, - [CrasDlcIntelligoBeamforming] = - cras_s2_get_beamforming_supported(), - }, - }); + cras_dlc_manager_init(); rc = dbus_threads_init_default(); if (!rc) { diff --git a/cras/src/server/cras_server_metrics.c b/cras/src/server/cras_server_metrics.c index a6cc69935..0c14f5cc4 100644 --- a/cras/src/server/cras_server_metrics.c +++ b/cras/src/server/cras_server_metrics.c @@ -279,7 +279,7 @@ struct cras_server_metrics_rtc_data { }; struct cras_server_metrics_dlc_manager_data { - enum CrasDlcId dlc_id; + struct CrasDlcId128 dlc_id; int elapsed_seconds; }; @@ -427,19 +427,6 @@ static inline const char* metrics_client_type_str( } } -static inline const char* metrics_dlc_id_str(enum CrasDlcId dlc_id) { - switch (dlc_id) { - case CrasDlcSrBt: - return "SrBt"; - case CrasDlcNcAp: - return "NcAp"; - case CrasDlcIntelligoBeamforming: - return "IntelligoBeamforming"; - default: - return "InvalidDlcId"; - } -} - static inline const char* metrics_stream_type_str( enum CRAS_STREAM_TYPE stream_type) { switch (stream_type) { @@ -773,7 +760,7 @@ int cras_server_metrics_hfp_mic_sr_status( } int cras_server_metrics_dlc_install_elapsed_time_on_success( - enum CrasDlcId dlc_id, + struct CrasDlcId128 dlc_id, int elapsed_seconds) { struct cras_server_metrics_message msg = CRAS_MAIN_MESSAGE_INIT; union cras_server_metrics_data data; @@ -796,7 +783,7 @@ int cras_server_metrics_dlc_install_elapsed_time_on_success( } int cras_server_metrics_dlc_install_elapsed_time_on_failure( - enum CrasDlcId dlc_id, + struct CrasDlcId128 dlc_id, int32_t elapsed_seconds) { struct cras_server_metrics_message msg = CRAS_MAIN_MESSAGE_INIT; union cras_server_metrics_data data; @@ -1919,7 +1906,7 @@ static void metrics_dlc_install_elapsed_time_on_success( snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.ElapsedTimeHistogramOnSuccess.%s", kCrasDlcManagerStatus, - metrics_dlc_id_str(data.dlc_id)); + data.dlc_id.id); cras_metrics_log_histogram(metrics_name, data.elapsed_seconds, DLC_INSTALL_ELAPSED_TIME_MIN_SECONDS, DLC_INSTALL_ELAPSED_TIME_MAX_SECONDS, @@ -1932,7 +1919,7 @@ static void metrics_dlc_install_elapsed_time_on_failure( snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.ElapsedTimeHistogramOnFailure.%s", kCrasDlcManagerStatus, - metrics_dlc_id_str(data.dlc_id)); + data.dlc_id.id); cras_metrics_log_histogram(metrics_name, data.elapsed_seconds, DLC_INSTALL_ELAPSED_TIME_MIN_SECONDS, DLC_INSTALL_ELAPSED_TIME_MAX_SECONDS, diff --git a/cras/src/server/cras_server_metrics.h b/cras/src/server/cras_server_metrics.h index 91e1dd1f3..058afb1ac 100644 --- a/cras/src/server/cras_server_metrics.h +++ b/cras/src/server/cras_server_metrics.h @@ -234,12 +234,12 @@ int cras_server_metrics_hfp_mic_sr_status( // Logs the elapsed time when cras_dlc_manager successfully download the dlc. int cras_server_metrics_dlc_install_elapsed_time_on_success( - enum CrasDlcId dlc_id, + struct CrasDlcId128 dlc_id, int elapsed_seconds); // Logs the elapsed time when cras_dlc_manager fails to download the dlc. int cras_server_metrics_dlc_install_elapsed_time_on_failure( - enum CrasDlcId dlc_id, + struct CrasDlcId128 dlc_id, int elapsed_seconds); // Logs whether AP NC has successfully started or not. diff --git a/cras/src/server/cras_sr_bt_util.c b/cras/src/server/cras_sr_bt_util.c index 5f0230463..0404ef465 100644 --- a/cras/src/server/cras_sr_bt_util.c +++ b/cras/src/server/cras_sr_bt_util.c @@ -26,7 +26,7 @@ enum CRAS_SR_BT_CAN_BE_ENABLED_STATUS cras_sr_bt_can_be_enabled() { } // else: feature is force enabled. - if (!cras_dlc_is_available(CrasDlcSrBt)) { + if (!cras_dlc_is_sr_bt_available()) { return CRAS_SR_BT_CAN_BE_ENABLED_STATUS_DLC_UNAVAILABLE; } return CRAS_SR_BT_CAN_BE_ENABLED_STATUS_OK; @@ -34,7 +34,7 @@ enum CRAS_SR_BT_CAN_BE_ENABLED_STATUS cras_sr_bt_can_be_enabled() { struct cras_sr_model_spec cras_sr_bt_get_model_spec( enum cras_sr_bt_model model) { - char* dlc_root = cras_dlc_get_root_path(CrasDlcSrBt); + char* dlc_root = cras_dlc_get_sr_bt_root_path(); struct cras_sr_model_spec spec = {}; switch (model) { case SR_BT_NBS: { diff --git a/cras/src/tests/cras_sr_bt_util_unittest.cc b/cras/src/tests/cras_sr_bt_util_unittest.cc index 411ccb169..6e5f3d17d 100644 --- a/cras/src/tests/cras_sr_bt_util_unittest.cc +++ b/cras/src/tests/cras_sr_bt_util_unittest.cc @@ -67,8 +67,7 @@ TEST_P(SrBtUtilTest, TestExpectedStatus) { GetParam().cras_system_get_force_sr_bt_enabled_return_value; cras_system_get_sr_bt_supported_return_value = GetParam().cras_system_get_sr_bt_supported_return_value; - cras_dlc_override_state_for_testing(CrasDlcSrBt, GetParam().dlc_is_installed, - nullptr); + cras_dlc_override_sr_bt_for_testing(GetParam().dlc_is_installed, nullptr); cras_system_get_sr_bt_enabled_return_value = GetParam().cras_system_get_sr_bt_enabled_return_value; diff --git a/cras/src/tests/iodev_list_unittest.cc b/cras/src/tests/iodev_list_unittest.cc index 446064ecc..c53cd275b 100644 --- a/cras/src/tests/iodev_list_unittest.cc +++ b/cras/src/tests/iodev_list_unittest.cc @@ -3578,7 +3578,7 @@ TEST_F(IoDevTestSuite, StyleTransferSupported) { EXPECT_EQ(server_state_stub.output_nodes[0].audio_effect, 0); cras_iodev_list_rm(&d1_); - cras_s2_set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + cras_s2_set_dlc_installed_for_test("nc-ap-dlc", true); cras_iodev_list_add(&d1_); EXPECT_EQ(server_state_stub.input_nodes[0].audio_effect, EFFECT_TYPE_STYLE_TRANSFER); @@ -3590,7 +3590,7 @@ TEST_F(IoDevTestSuite, ResetForStyleTransfer) { cras_s2_reset_for_testing(); cras_s2_set_ap_nc_segmentation_allowed(true); cras_s2_set_style_transfer_featured_allowed(true); - cras_s2_set_dlc_installed(CrasDlcId::CrasDlcNcAp, true); + cras_s2_set_dlc_installed_for_test("nc-ap-dlc", true); struct cras_rstream rstream; int rc; diff --git a/cras/src/tests/server_metrics_unittest.cc b/cras/src/tests/server_metrics_unittest.cc index 54ede17d8..c369254a6 100644 --- a/cras/src/tests/server_metrics_unittest.cc +++ b/cras/src/tests/server_metrics_unittest.cc @@ -502,7 +502,7 @@ INSTANTIATE_TEST_SUITE_P( .status = CRAS_METRICS_HFP_MIC_SR_FEATURE_DISABLED}))); struct CrasDlcManagerTestParam { - enum CrasDlcId dlc_id; + struct CrasDlcId128 dlc_id; std::string dlc_id_str; int success_time; std::vector elapsed_seconds; @@ -545,11 +545,11 @@ TEST_P(ServerMetricsCrasDlcManagerTest, TestCrasServerMetricsDlcManagerStatus) { INSTANTIATE_TEST_SUITE_P( , ServerMetricsCrasDlcManagerTest, - testing::Values(CrasDlcManagerTestParam({.dlc_id = CrasDlcNcAp, - .dlc_id_str = "NcAp", + testing::Values(CrasDlcManagerTestParam({.dlc_id = {.id = "nc-ap-dlc"}, + .dlc_id_str = "nc-ap-dlc", .success_time = 0}), - CrasDlcManagerTestParam({.dlc_id = CrasDlcSrBt, - .dlc_id_str = "SrBt", + CrasDlcManagerTestParam({.dlc_id = {.id = "sr-bt-dlc"}, + .dlc_id_str = "sr-bt-dlc", .success_time = 487, .elapsed_seconds = {0, 1, 3, 7, 15, 31, 63, 127,