1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 use std::io; 5 use std::io::{Read, Write}; 6 use std::mem; 7 use std::os::unix::{ 8 io::{AsRawFd, RawFd}, 9 net::UnixStream, 10 }; 11 use std::time::Duration; 12 13 use cras_sys::gen::{audio_message, CRAS_AUDIO_MESSAGE_ID}; 14 use data_model::DataInit; 15 use sys_util::{PollContext, PollToken}; 16 17 /// A structure for interacting with the CRAS server audio thread through a `UnixStream::pair`. 18 pub struct AudioSocket { 19 socket: UnixStream, 20 } 21 22 /// Audio message results which are exchanged by `CrasStream` and CRAS audio server. 23 /// through an audio socket. 24 #[allow(dead_code)] 25 #[derive(Debug)] 26 pub enum AudioMessage { 27 /// * `id` - Audio message id, which is a `enum CRAS_AUDIO_MESSAGE_ID`. 28 /// * `frames` - A `u32` indicating the read or written frame count. 29 Success { 30 id: CRAS_AUDIO_MESSAGE_ID, 31 frames: u32, 32 }, 33 /// * `error` - Error code when a error occurs. 34 Error(i32), 35 } 36 37 /// Converts AudioMessage to raw audio_message for CRAS audio server. 38 impl Into<audio_message> for AudioMessage { into(self) -> audio_message39 fn into(self) -> audio_message { 40 match self { 41 AudioMessage::Success { id, frames } => audio_message { 42 id, 43 error: 0, 44 frames, 45 }, 46 AudioMessage::Error(error) => audio_message { 47 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, 48 error, 49 frames: 0, 50 }, 51 } 52 } 53 } 54 55 /// Converts AudioMessage from raw audio_message from CRAS audio server. 56 impl From<audio_message> for AudioMessage { from(message: audio_message) -> Self57 fn from(message: audio_message) -> Self { 58 match message.error { 59 0 => AudioMessage::Success { 60 id: message.id as CRAS_AUDIO_MESSAGE_ID, 61 frames: message.frames, 62 }, 63 error => AudioMessage::Error(error), 64 } 65 } 66 } 67 68 impl AudioSocket { 69 /// Creates `AudioSocket` from a `UnixStream`. 70 /// 71 /// # Arguments 72 /// `socket` - A `UnixStream`. new(socket: UnixStream) -> Self73 pub fn new(socket: UnixStream) -> Self { 74 AudioSocket { socket } 75 } 76 read_from_socket<T>(&mut self) -> io::Result<T> where T: Sized + DataInit + Default,77 fn read_from_socket<T>(&mut self) -> io::Result<T> 78 where 79 T: Sized + DataInit + Default, 80 { 81 let mut message: T = Default::default(); 82 let rc = self.socket.read(message.as_mut_slice())?; 83 if rc == mem::size_of::<T>() { 84 Ok(message) 85 } else { 86 Err(io::Error::new(io::ErrorKind::Other, "Read truncated data.")) 87 } 88 } 89 90 /// Blocks reading an `audio message`. 91 /// 92 /// # Returns 93 /// `AudioMessage` - AudioMessage enum. 94 /// 95 /// # Errors 96 /// Returns io::Error if error occurs. read_audio_message(&mut self) -> io::Result<AudioMessage>97 pub fn read_audio_message(&mut self) -> io::Result<AudioMessage> { 98 match self.read_audio_message_with_timeout(None)? { 99 None => Err(io::Error::new(io::ErrorKind::Other, "Unexpected exit")), 100 Some(message) => Ok(message), 101 } 102 } 103 104 /// Blocks waiting for an `audio message` until `timeout` occurs. If `timeout` 105 /// is None, blocks indefinitely. 106 /// 107 /// # Returns 108 /// Some(AudioMessage) - AudioMessage enum if we receive a message before timeout. 109 /// None - If the timeout expires. 110 /// 111 /// # Errors 112 /// Returns io::Error if error occurs. read_audio_message_with_timeout( &mut self, timeout: Option<Duration>, ) -> io::Result<Option<AudioMessage>>113 pub fn read_audio_message_with_timeout( 114 &mut self, 115 timeout: Option<Duration>, 116 ) -> io::Result<Option<AudioMessage>> { 117 #[derive(PollToken)] 118 enum Token { 119 AudioMsg, 120 } 121 let poll_ctx: PollContext<Token> = 122 match PollContext::new().and_then(|pc| pc.add(self, Token::AudioMsg).and(Ok(pc))) { 123 Ok(pc) => pc, 124 Err(e) => { 125 return Err(io::Error::new( 126 io::ErrorKind::Other, 127 format!("Failed to create PollContext: {}", e), 128 )); 129 } 130 }; 131 let events = { 132 let result = match timeout { 133 None => poll_ctx.wait(), 134 Some(duration) => poll_ctx.wait_timeout(duration), 135 }; 136 match result { 137 Ok(v) => v, 138 Err(e) => { 139 return Err(io::Error::new( 140 io::ErrorKind::Other, 141 format!("Failed to poll: {:?}", e), 142 )); 143 } 144 } 145 }; 146 147 // Check the first readable message 148 let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect(); 149 match tokens.get(0) { 150 None => Ok(None), 151 Some(&Token::AudioMsg) => { 152 let raw_msg: audio_message = self.read_from_socket()?; 153 Ok(Some(AudioMessage::from(raw_msg))) 154 } 155 } 156 } 157 158 /// Sends raw audio message with given AudioMessage enum. 159 /// 160 /// # Arguments 161 /// * `msg` - enum AudioMessage, which could be `Success` with message id 162 /// and frames or `Error` with error code. 163 /// 164 /// # Errors 165 /// Returns error if `libc::write` fails. send_audio_message(&mut self, msg: AudioMessage) -> io::Result<()>166 fn send_audio_message(&mut self, msg: AudioMessage) -> io::Result<()> { 167 let msg: audio_message = msg.into(); 168 let rc = self.socket.write(msg.as_slice())?; 169 if rc < mem::size_of::<audio_message>() { 170 Err(io::Error::new(io::ErrorKind::Other, "Sent truncated data.")) 171 } else { 172 Ok(()) 173 } 174 } 175 176 /// Sends the data ready message with written frame count. 177 /// 178 /// # Arguments 179 /// * `frames` - An `u32` indicating the written frame count. data_ready(&mut self, frames: u32) -> io::Result<()>180 pub fn data_ready(&mut self, frames: u32) -> io::Result<()> { 181 self.send_audio_message(AudioMessage::Success { 182 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, 183 frames, 184 }) 185 } 186 187 /// Sends the capture ready message with read frame count. 188 /// 189 /// # Arguments 190 /// 191 /// * `frames` - An `u32` indicating the number of read frames. capture_ready(&mut self, frames: u32) -> io::Result<()>192 pub fn capture_ready(&mut self, frames: u32) -> io::Result<()> { 193 self.send_audio_message(AudioMessage::Success { 194 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_CAPTURED, 195 frames, 196 }) 197 } 198 } 199 200 impl AsRawFd for AudioSocket { as_raw_fd(&self) -> RawFd201 fn as_raw_fd(&self) -> RawFd { 202 self.socket.as_raw_fd() 203 } 204 } 205 206 #[cfg(test)] 207 mod tests { 208 use super::*; 209 210 // PartialEq for comparing AudioMessage in tests 211 impl PartialEq for AudioMessage { eq(&self, other: &Self) -> bool212 fn eq(&self, other: &Self) -> bool { 213 match (self, other) { 214 ( 215 AudioMessage::Success { id, frames }, 216 AudioMessage::Success { 217 id: other_id, 218 frames: other_frames, 219 }, 220 ) => id == other_id && frames == other_frames, 221 (AudioMessage::Error(err), AudioMessage::Error(other_err)) => err == other_err, 222 _ => false, 223 } 224 } 225 } 226 init_audio_socket_pair() -> (AudioSocket, AudioSocket)227 fn init_audio_socket_pair() -> (AudioSocket, AudioSocket) { 228 let (sock1, sock2) = UnixStream::pair().unwrap(); 229 let sender = AudioSocket::new(sock1); 230 let receiver = AudioSocket::new(sock2); 231 (sender, receiver) 232 } 233 234 #[test] audio_socket_send_and_recv_audio_message()235 fn audio_socket_send_and_recv_audio_message() { 236 let (mut sender, mut receiver) = init_audio_socket_pair(); 237 let message_succ = AudioMessage::Success { 238 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, 239 frames: 0, 240 }; 241 sender.send_audio_message(message_succ).unwrap(); 242 let res = receiver.read_audio_message().unwrap(); 243 assert_eq!( 244 res, 245 AudioMessage::Success { 246 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, 247 frames: 0 248 } 249 ); 250 251 let message_err = AudioMessage::Error(123); 252 sender.send_audio_message(message_err).unwrap(); 253 let res = receiver.read_audio_message().unwrap(); 254 assert_eq!(res, AudioMessage::Error(123)); 255 } 256 257 #[test] audio_socket_data_ready_send_and_recv()258 fn audio_socket_data_ready_send_and_recv() { 259 let (sock1, sock2) = UnixStream::pair().unwrap(); 260 let mut audio_socket_send = AudioSocket::new(sock1); 261 let mut audio_socket_recv = AudioSocket::new(sock2); 262 audio_socket_send.data_ready(256).unwrap(); 263 264 // Test receiving by using raw audio_message since CRAS audio server use this. 265 let audio_msg: audio_message = audio_socket_recv.read_from_socket().unwrap(); 266 let ref_audio_msg = audio_message { 267 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, 268 error: 0, 269 frames: 256, 270 }; 271 // Use brace to copy unaligned data locally 272 assert_eq!({ audio_msg.id }, { ref_audio_msg.id }); 273 assert_eq!({ audio_msg.error }, { ref_audio_msg.error }); 274 assert_eq!({ audio_msg.frames }, { ref_audio_msg.frames }); 275 } 276 277 #[test] audio_socket_capture_ready()278 fn audio_socket_capture_ready() { 279 let (sock1, sock2) = UnixStream::pair().unwrap(); 280 let mut audio_socket_send = AudioSocket::new(sock1); 281 let mut audio_socket_recv = AudioSocket::new(sock2); 282 audio_socket_send 283 .capture_ready(256) 284 .expect("Failed to send capture ready message."); 285 286 // Test receiving by using raw audio_message since CRAS audio server use this. 287 let audio_msg: audio_message = audio_socket_recv 288 .read_from_socket() 289 .expect("Failed to read audio message from AudioSocket."); 290 let ref_audio_msg = audio_message { 291 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_CAPTURED, 292 error: 0, 293 frames: 256, 294 }; 295 // Use brace to copy unaligned data locally 296 assert_eq!({ audio_msg.id }, { ref_audio_msg.id }); 297 assert_eq!({ audio_msg.error }, { ref_audio_msg.error }); 298 assert_eq!({ audio_msg.frames }, { ref_audio_msg.frames }); 299 } 300 301 #[test] audio_socket_send_when_broken_pipe()302 fn audio_socket_send_when_broken_pipe() { 303 let sock1 = { 304 let (sock1, _) = UnixStream::pair().unwrap(); 305 sock1 306 }; 307 let mut audio_socket = AudioSocket::new(sock1); 308 let res = audio_socket.data_ready(256); 309 //Broken pipe 310 assert_eq!( 311 res.expect_err("Result should be an error.").kind(), 312 io::Error::from_raw_os_error(32).kind(), 313 "Error should be broken pipe.", 314 ); 315 } 316 } 317