Integrate audio_streams into crosvm, add stub libcras implementation

The `# ignored by ebuild` tag will remove the path to libcras_stub and
allows crosvm to be built with the actual libcras implementation.

This allows all other platforms to build without depending on
`third_party/adhd/cras/client/libcras`, which is a prerequisite for
externalizing crosvm.

An empty libcras_stub crate is provided to keep cargo happy in external
builds.

To build with cargo against libcras, the setup_cros_cargo.sh script
can be used.

BUG=b:191511078
TEST=Tests in crosvm and cros_sdk both pass:
  $ ./test_all
  $ cros_run_unit_tests --package=crosvm

Cq-Depend: chromium:2993483
Change-Id: I86aad23a86c78e580c1724fb311f870b25d6b09e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2988154
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Dennis Kempin <denniskempin@google.com>
Reviewed-by: Chih-Yang Hsia <paulhsia@chromium.org>
This commit is contained in:
Dennis Kempin 2021-06-23 11:34:31 -07:00 committed by Commit Bot
parent f1dd5afb9a
commit 50a58f9372
15 changed files with 85 additions and 40 deletions

17
Cargo.lock generated
View file

@ -86,6 +86,8 @@ dependencies = [
name = "audio_streams"
version = "0.1.0"
dependencies = [
"async-trait",
"cros_async",
"sync",
"sys_util",
]
@ -166,14 +168,6 @@ dependencies = [
"bitflags",
]
[[package]]
name = "cras-sys"
version = "0.1.0"
dependencies = [
"audio_streams",
"data_model",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -621,13 +615,6 @@ checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
[[package]]
name = "libcras"
version = "0.1.0"
dependencies = [
"audio_streams",
"cras-sys",
"data_model",
"libc",
"sys_util",
]
[[package]]
name = "libcrosvm_control"

View file

@ -43,11 +43,13 @@ exclude = [
"sys_util",
"tempfile",
"vm_memory",
"audio_streams",
]
[features]
audio = ["devices/audio"]
chromeos = ["base/chromeos"]
audio_cras = ["devices/audio_cras"]
chromeos = ["base/chromeos", "audio_cras"]
composite-disk = ["protos/composite-disk", "protobuf", "disk/composite-disk"]
default = ["audio", "gpu", "usb"]
default-no-sandbox = []
@ -113,12 +115,11 @@ base = "*"
[patch.crates-io]
assertions = { path = "assertions" }
audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by ebuild
audio_streams = { path = "audio_streams" }
base = { path = "base" }
cras-sys = { path = "../../third_party/adhd/cras/client/cras-sys" } # ignored by ebuild
cros_fuzz = { path = "../../platform2/cros-fuzz" } # ignored by ebuild
data_model = { path = "data_model" }
libcras = { path = "../../third_party/adhd/cras/client/libcras" } # ignored by ebuild
libcras = { path = "libcras_stub" } # ignored by ebuild
minijail = { path = "../../aosp/external/minijail/rust/minijail" } # ignored by ebuild
p9 = { path = "../../platform2/vm_tools/p9" } # ignored by ebuild
sync = { path = "sync" }

View file

@ -1,2 +0,0 @@
Cargo.lock
target

View file

@ -1,7 +0,0 @@
rust_library_rlib {
name: "libaudio_streams",
host_supported: true,
crate_name: "audio_streams",
edition: "2018",
srcs: ["src/audio_streams.rs"],
}

View file

@ -9,6 +9,6 @@ path = "src/audio_streams.rs"
[dependencies]
async-trait = "0.1.36"
cros_async = { path = "../../../platform/crosvm/cros_async" } # provided by ebuild
sync = { path = "../../../platform/crosvm/sync" } # provided by ebuild
sys_util = { path = "../../../platform/crosvm/sys_util" } # provided by ebuild
cros_async = { path = "../cros_async" } # provided by ebuild
sync = { path = "../sync" } # provided by ebuild
sys_util = { path = "../sys_util" } # provided by ebuild

View file

@ -65,6 +65,27 @@ SUPPRESS=(
new-ret-no-self
)
FEATURES=(
default
direct
audio
gpu
plugin
power-monitor-powerd
tpm
usb
video-decoder
video-encoder
wl-dmabuf
x
virgl_renderer_next
composite-disk
virgl_renderer
gfxstream
gdb
)
printf -v FEATURES_LIST '%s,' "${FEATURES[@]}"
# Needed or else clippy won't re-run on code that has already compiled.
if [[ "${USE_CACHE}" == false ]]; then
cargo clean
@ -76,5 +97,5 @@ RUST_SYSROOT=$(rustc --print sysroot)
RUSTFLAGS="${RUSTFLAGS:-}"
export RUSTFLAGS="$RUSTFLAGS --sysroot=$RUST_SYSROOT"
cargo clippy --all-features --all-targets -- ${SUPPRESS[@]/#/-Aclippy::} \
"${CLIPPY_ARGS[@]}" -D warnings
cargo clippy --features ${FEATURES_LIST} --all-targets -- \
${SUPPRESS[@]/#/-Aclippy::} "${CLIPPY_ARGS[@]}" -D warnings

View file

@ -6,6 +6,7 @@ edition = "2018"
[features]
audio = []
audio_cras = ["libcras"]
direct = []
gpu = ["gpu_display","rutabaga_gfx"]
tpm = ["protos/trunks", "tpm2"]
@ -32,7 +33,7 @@ rutabaga_gfx = { path = "../rutabaga_gfx", optional = true }
hypervisor = { path = "../hypervisor" }
kvm_sys = { path = "../kvm_sys" }
libc = "*"
libcras = "*"
libcras = { version = "*", optional = true }
libvda = { path = "../libvda", optional = true }
linux_input_sys = { path = "../linux_input_sys" }
minijail = "*"

View file

@ -10,6 +10,7 @@ use std::str::FromStr;
use audio_streams::shm_streams::{NullShmStreamSource, ShmStreamSource};
use base::{error, Event, RawDescriptor};
#[cfg(feature = "audio_cras")]
use libcras::{CrasClient, CrasClientType, CrasSocketType, CrasSysError};
use resources::{Alloc, MmioType, SystemAllocator};
use vm_memory::GuestMemory;
@ -39,6 +40,7 @@ const PCI_DEVICE_ID_INTEL_82801AA_5: u16 = 0x2415;
#[derive(Debug, Clone)]
pub enum Ac97Backend {
NULL,
#[cfg(feature = "audio_cras")]
CRAS,
VIOS,
}
@ -71,6 +73,7 @@ impl FromStr for Ac97Backend {
type Err = Ac97Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
#[cfg(feature = "audio_cras")]
"cras" => Ok(Ac97Backend::CRAS),
"vios" => Ok(Ac97Backend::VIOS),
"null" => Ok(Ac97Backend::NULL),
@ -85,6 +88,7 @@ pub struct Ac97Parameters {
pub backend: Ac97Backend,
pub capture: bool,
pub vios_server_path: Option<PathBuf>,
#[cfg(feature = "audio_cras")]
client_type: Option<CrasClientType>,
}
@ -92,6 +96,7 @@ impl Ac97Parameters {
/// Set CRAS client type by given client type string.
///
/// `client_type` - The client type string.
#[cfg(feature = "audio_cras")]
pub fn set_client_type(&mut self, client_type: &str) -> std::result::Result<(), CrasSysError> {
self.client_type = Some(client_type.parse()?);
Ok(())
@ -145,6 +150,7 @@ impl Ac97Dev {
/// to create `Ac97Dev` with the given back-end, it'll fallback to the null audio device.
pub fn try_new(mem: GuestMemory, param: Ac97Parameters) -> Result<Self> {
match param.backend {
#[cfg(feature = "audio_cras")]
Ac97Backend::CRAS => Self::create_cras_audio_device(param, mem.clone()).or_else(|e| {
error!(
"Ac97Dev: create_cras_audio_device: {}. Fallback to null audio device",
@ -160,12 +166,14 @@ impl Ac97Dev {
/// Return the minijail policy file path for the current Ac97Dev.
pub fn minijail_policy(&self) -> &'static str {
match self.backend {
#[cfg(feature = "audio_cras")]
Ac97Backend::CRAS => "cras_audio_device",
Ac97Backend::VIOS => "vios_audio_device",
Ac97Backend::NULL => "null_audio_device",
}
}
#[cfg(feature = "audio_cras")]
fn create_cras_audio_device(params: Ac97Parameters, mem: GuestMemory) -> Result<Self> {
let mut server = Box::new(
CrasClient::with_type(CrasSocketType::Unified)

View file

@ -27,7 +27,7 @@ pub enum Error {
/// Registering an IO BAR failed.
IoRegistrationFailed(u64, pci_configuration::Error),
/// Create cras client failed.
#[cfg(feature = "audio")]
#[cfg(all(feature = "audio", feature = "audio_cras"))]
CreateCrasClientFailed(libcras::Error),
/// Create VioS client failed.
#[cfg(feature = "audio")]
@ -45,7 +45,7 @@ impl Display for Error {
match self {
CapabilitiesSetup(e) => write!(f, "failed to add capability {}", e),
#[cfg(feature = "audio")]
#[cfg(all(feature = "audio", feature = "audio_cras"))]
CreateCrasClientFailed(e) => write!(f, "failed to create CRAS Client: {}", e),
#[cfg(feature = "audio")]
CreateViosClientFailed(e) => write!(f, "failed to create VioS Client: {}", e),

8
libcras_stub/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "libcras"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
[lib]
path = "src/libcras.rs"

12
libcras_stub/README.md Normal file
View file

@ -0,0 +1,12 @@
# Stub crate for libcras
libcras is used by ChromeOS to play audio through the cras server.
In ChromeOS builds, the `audio_cras` cargo feature is enabled and this crate is
replaced with the actual [libcras] implementation.
On other platforms, the feature flag will remain disabled and this crate is used
to satisfy cargo dependencies on libcras.
[libcras]:
https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/adhd/cras/client/libcras/

View file

@ -0,0 +1 @@

View file

@ -72,7 +72,7 @@ CRATE_REQUIREMENTS: Dict[str, List[Requirements]] = {
# Just like for crates, lists requirements for each cargo feature flag.
FEATURE_REQUIREMENTS: Dict[str, List[Requirements]] = {
"chromeos": [],
"chromeos": [Requirements.DISABLED],
"audio": [],
"gpu": [Requirements.CROS_BUILD],
"plugin": [Requirements.PRIVILEGED, Requirements.X86_64],

14
setup_cros_cargo.sh Executable file
View file

@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file
#
# To build crosvm using cargo against libraries and crates provided by ChromeOS
# use this script to update path references in Cargo.toml.
#
# TODO(b/194323235): Add documentation for ChromeOS developer workflows.
sed -i 's|path = "libcras_stub"|path = "../../third_party/adhd/cras/client/libcras"|g' \
Cargo.toml
echo "Modified Cargo.toml with new paths. Please do not commit those."

View file

@ -533,6 +533,7 @@ fn parse_ac97_options(s: &str) -> argument::Result<Ac97Parameters> {
argument::Error::Syntax(format!("invalid capture option: {}", e))
})?;
}
#[cfg(feature = "audio_cras")]
"client_type" => {
ac97_params
.set_client_type(v)
@ -2800,7 +2801,7 @@ mod tests {
);
}
#[cfg(feature = "audio")]
#[cfg(feature = "audio_cras")]
#[test]
fn parse_ac97_vaild() {
parse_ac97_options("backend=cras").expect("parse should have succeded");
@ -2812,13 +2813,13 @@ mod tests {
parse_ac97_options("backend=null").expect("parse should have succeded");
}
#[cfg(feature = "audio")]
#[cfg(feature = "audio_cras")]
#[test]
fn parse_ac97_capture_vaild() {
parse_ac97_options("backend=cras,capture=true").expect("parse should have succeded");
}
#[cfg(feature = "audio")]
#[cfg(feature = "audio_cras")]
#[test]
fn parse_ac97_client_type() {
parse_ac97_options("backend=cras,capture=true,client_type=crosvm")