sl4f_lib/virtual_camera/
facade.rsuse anyhow::Error;
use fidl_fuchsia_camera_test_virtualcamera::{
StreamConfig, VirtualCameraDeviceMarker, VirtualCameraDeviceProxy,
};
use fuchsia_component::client::connect_to_protocol;
use serde_json::{to_value, Value};
use tracing::*;
#[derive(Debug)]
pub struct VirtualCameraFacade {
camera_proxy: Option<VirtualCameraDeviceProxy>,
}
impl VirtualCameraFacade {
pub fn new() -> VirtualCameraFacade {
VirtualCameraFacade { camera_proxy: None }
}
pub async fn add_stream_config(&self, args: Value) -> Result<Value, Error> {
let config_index =
args["index"].as_u64().ok_or_else(|| format_err!("index not a number"))?.try_into()?;
info!("AddStreamConfig: index received {:?}", config_index);
let config_width = (args
.get("width")
.ok_or_else(|| format_err!("Expected a serde_json Value width."))?
.as_u64()
.ok_or_else(|| format_err!("Expected u64 type for width."))?
as u32)
.try_into()?;
info!("AddStreamConfig: width received {:?}", config_width);
let config_height = (args
.get("height")
.ok_or_else(|| format_err!("Expected a serde_json Value height."))?
.as_u64()
.ok_or_else(|| format_err!("Expected u64 type for height."))?
as u32)
.try_into()?;
info!("AddStreamConfig: height received {:?}", config_height);
let camera_proxy = match self.camera_proxy.as_ref() {
Some(proxy) => proxy.clone(),
None => match connect_to_protocol::<VirtualCameraDeviceMarker>() {
Ok(proxy) => proxy,
Err(e) => bail!("Failed to connect to VirtualCameraDevice FIDL service {:?}.", e),
},
};
let stream_config =
{ StreamConfig { width: config_width, height: config_height, ..Default::default() } };
info!("Stream Config specifications {:?}", stream_config);
match camera_proxy.add_stream_config(config_index, &stream_config) {
Ok(_) => Ok(to_value(true)?),
Err(e) => Err(format_err!("AddStreamConfig failed with err {:?}", e)),
}
}
pub async fn add_to_device_watcher(&self) -> Result<Value, Error> {
let camera_proxy = match self.camera_proxy.as_ref() {
Some(proxy) => proxy.clone(),
None => match connect_to_protocol::<VirtualCameraDeviceMarker>() {
Ok(proxy) => proxy,
Err(e) => bail!("Failed to connect to VirtualCameraDevice FIDL service {:?}.", e),
},
};
info!("AddToDeviceWatcher FIDL protocol connected");
match camera_proxy.add_to_device_watcher().await? {
Ok(_) => Ok(to_value(true)?),
Err(e) => Err(format_err!("AddToDeviceWatcher failed with err {:?}", e)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use fidl::endpoints::{create_proxy, create_proxy_and_stream};
use fidl_fuchsia_camera_test_virtualcamera::VirtualCameraDeviceRequest;
use fuchsia_async as fasync;
use futures::prelude::*;
use futures::TryStreamExt;
use serde_json::json;
#[fasync::run_singlethreaded(test)]
async fn test_add_stream_config() {
let test_index = 0;
let test_width = 100;
let test_height = 200;
let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
let facade_fut = async move {
assert_eq!(
facade
.add_stream_config(
json!({"index": test_index, "width": test_width, "height": test_height})
)
.await
.unwrap(),
to_value(true).unwrap()
);
};
let stream_fut = async move {
match stream.try_next().await {
Ok(Some(VirtualCameraDeviceRequest::AddStreamConfig { index, config, .. })) => {
assert_eq!(index, test_index);
assert_eq!(
config,
StreamConfig {
width: Some(test_width),
height: Some(test_height),
..Default::default()
}
);
}
err => panic!("Err in request handler: {:?}", err),
}
};
future::join(facade_fut, stream_fut).await;
}
#[fasync::run_singlethreaded(test)]
async fn test_add_stream_config_with_parameter_error() {
let test_index = "one";
let test_width = "three hundred";
let test_height = "four hundred";
let proxy = create_proxy::<VirtualCameraDeviceMarker>();
let facade = VirtualCameraFacade { camera_proxy: Some(proxy.0) };
assert_eq!(
facade
.add_stream_config(
json!({"index": test_index, "width": test_width, "height": test_height})
)
.await
.is_ok(),
false
);
}
#[fasync::run_singlethreaded(test)]
async fn test_add_to_device_watcher() {
let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
let facade_fut = async move {
assert_eq!(facade.add_to_device_watcher().await.unwrap(), to_value(true).unwrap());
};
let stream_fut = async move {
match stream.try_next().await {
Ok(Some(VirtualCameraDeviceRequest::AddToDeviceWatcher { responder })) => {
responder.send(Ok(())).unwrap();
}
err => panic!("Err in request handler: {:?}", err),
}
};
future::join(facade_fut, stream_fut).await;
}
#[fasync::run_singlethreaded(test)]
async fn test_add_to_device_watcher_on_error() {
let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
let facade_fut = async move {
assert_eq!(facade.add_to_device_watcher().await.is_ok(), false);
};
let stream_fut = async move {
match stream.try_next().await {
Ok(Some(VirtualCameraDeviceRequest::AddToDeviceWatcher { responder })) => {
responder.send(
Err(fidl_fuchsia_camera_test_virtualcamera::
Error::AlreadyAddedToDeviceWatcher
)).unwrap();
}
err => panic!("Err in request handler: {:?}", err),
}
};
future::join(facade_fut, stream_fut).await;
}
}