linux: Add ac97 device with CRAS backend

Add an ac97 device that plays audio through CRAS audio server.

BUG=chromium:781398
BUG=chromium:907520
TEST=Test building by $ cargo build
TEST=Deploy crosvm to DUT and test audio functionality
CQ-DEPEND=CL:1429311
CQ-DEPEND=CL:1429542

Change-Id: Ia273d8f1e82c20d1f1882f088886458339399aae
Reviewed-on: https://chromium-review.googlesource.com/1426282
Commit-Ready: Chih-Yang Hsia <paulhsia@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Chih-Yang Hsia <paulhsia@chromium.org>
Reviewed-by: Chih-Yang Hsia <paulhsia@chromium.org>
This commit is contained in:
paulhsia 2019-01-22 15:22:25 +08:00 committed by chrome-bot
parent 3082e8e48d
commit f052cfefc8
6 changed files with 139 additions and 0 deletions

19
Cargo.lock generated
View file

@ -69,6 +69,13 @@ name = "cfg-if"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cras-sys"
version = "0.1.0"
dependencies = [
"data_model 0.1.0",
]
[[package]]
name = "crosvm"
version = "0.1.0"
@ -88,6 +95,7 @@ dependencies = [
"kvm 0.1.0",
"kvm_sys 0.1.0",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libcras 0.1.0",
"msg_socket 0.1.0",
"net_util 0.1.0",
"p9 0.1.0",
@ -231,6 +239,17 @@ name = "libc"
version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libcras"
version = "0.1.0"
dependencies = [
"audio_streams 0.1.0",
"cras-sys 0.1.0",
"data_model 0.1.0",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"sys_util 0.1.0",
]
[[package]]
name = "log"
version = "0.4.5"

View file

@ -44,6 +44,7 @@ usb_util = { path = "usb_util", optional = true }
kernel_cmdline = { path = "kernel_cmdline" }
kernel_loader = { path = "kernel_loader" }
libc = "=0.2.44"
libcras = "*"
byteorder = "=1.1.0"
net_util = { path = "net_util" }
vhost = { path = "vhost" }
@ -71,6 +72,7 @@ sys_util = "*"
assertions = { path = "assertions" }
audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by ebuild
data_model = { path = "data_model" }
libcras = { path = "../../third_party/adhd/cras/client/libcras" } # ignored by ebuild
poll_token_derive = { path = "sys_util/poll_token_derive" }
sync = { path = "sync" }
sys_util = { path = "sys_util" }

View file

@ -0,0 +1,49 @@
# Copyright 2019 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.
close: 1
dup: 1
dup2: 1
exit: 1
exit_group: 1
futex: 1
gettimeofday: 1
madvise: 1
# Disallow mmap with PROT_EXEC set. The syntax here doesn't allow bit
# negation, thus the manually negated mask constant.
mmap2: arg2 in 0xfffffffb
mprotect: arg2 in 0xfffffffb
munmap: 1
read: 1
recv: 1
sched_getaffinity: 1
set_robust_list: 1
sigaltstack: 1
# Disallow clone's other than new threads.
clone: arg0 & 0x00010000
write: 1
eventfd2: 1
nanosleep: 1
poll: 1
ppoll: 1
getpid: 1
# Allow PR_SET_NAME only.
prctl: arg0 == 15
prlimit64: 1
restart_syscall: 1
setrlimit: 1
epoll_create1: 1
epoll_ctl: 1
epoll_wait: 1
# Kill child thread when it fails
tgkill: 1
# Real time priority
rt_sigprocmask: 1
rt_sigaction: 1
rt_sigreturn: 1
# Sockets
recvmsg: 1
sendmsg: 1
socketpair: arg0 == AF_UNIX
clock_gettime: 1

View file

@ -0,0 +1,47 @@
# Copyright 2019 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.
close: 1
dup: 1
dup2: 1
exit: 1
exit_group: 1
futex: 1
# Disallow mmap with PROT_EXEC set. The syntax here doesn't allow bit
# negation, thus the manually negated mask constant.
mmap: arg2 in 0xfffffffb
mprotect: arg2 in 0xfffffffb
madvise: 1
munmap: 1
read: 1
recvfrom: 1
sched_getaffinity: 1
set_robust_list: 1
sigaltstack: 1
# Disallow clone's other than new threads.
clone: arg0 & 0x00010000
write: 1
eventfd2: 1
nanosleep: 1
poll: 1
ppoll: 1
getpid: 1
# Allow PR_SET_NAME only.
prctl: arg0 == 15
prlimit64: 1
restart_syscall: 1
setrlimit: 1
epoll_create1: 1
epoll_ctl: 1
epoll_wait: 1
# Kill child thread when it fails
tgkill: 1
# Real time priority
rt_sigprocmask: 1
rt_sigaction: 1
rt_sigreturn: 1
# Sockets
recvmsg: 1
sendmsg: 1
socketpair: arg0 == AF_UNIX

View file

@ -26,6 +26,7 @@ use byteorder::{ByteOrder, LittleEndian};
use devices::{self, PciDevice, VirtioPciDevice};
use io_jail::{self, Minijail};
use kvm::*;
use libcras::CrasClient;
use msg_socket::{MsgReceiver, MsgSender, MsgSocket, UnlinkMsgSocket};
use net_util::{Error as NetError, Tap};
use qcow::{self, ImageType, QcowFile};
@ -633,6 +634,20 @@ fn create_virtio_devs(
pci_devices.push((pci_dev, stub.jail));
}
if cfg.cras_audio {
let cras_audio_box = Box::new(devices::Ac97Dev::new(
(*mem).clone(),
Box::new(CrasClient::new()?),
));
let cras_audio_jail = if cfg.multiprocess {
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("cras_audio_device.policy");
Some(create_base_minijail(empty_root_path, &policy_path)?)
} else {
None
};
pci_devices.push((cras_audio_box, cras_audio_jail));
}
if cfg.null_audio {
let null_audio_box = Box::new(devices::Ac97Dev::new(
(*mem).clone(),

View file

@ -16,6 +16,7 @@ extern crate kernel_loader;
extern crate kvm;
extern crate kvm_sys;
extern crate libc;
extern crate libcras;
extern crate net_util;
extern crate qcow;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@ -93,6 +94,7 @@ pub struct Config {
multiprocess: bool,
seccomp_policy_dir: PathBuf,
gpu: bool,
cras_audio: bool,
null_audio: bool,
}
@ -120,6 +122,7 @@ impl Default for Config {
shared_dirs: Vec::new(),
multiprocess: !cfg!(feature = "default-no-sandbox"),
seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR),
cras_audio: false,
null_audio: false,
}
}
@ -212,6 +215,9 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
})?,
)
}
"cras-audio" => {
cfg.cras_audio = true;
}
"null-audio" => {
cfg.null_audio = true;
}
@ -497,6 +503,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
"IP address to assign to host tap interface."),
Argument::value("netmask", "NETMASK", "Netmask for VM subnet."),
Argument::value("mac", "MAC", "MAC address for VM."),
Argument::flag("cras-audio", "Add an audio device to the VM that plays samples through CRAS server"),
Argument::flag("null-audio", "Add an audio device to the VM that plays samples to /dev/null"),
Argument::value("wayland-sock", "PATH", "Path to the Wayland socket to use."),
#[cfg(feature = "wl-dmabuf")]