sl4f_lib/virtual_camera/
facade.rs1use anyhow::Error;
6use fidl_fuchsia_camera_test_virtualcamera::{
7 StreamConfig, VirtualCameraDeviceMarker, VirtualCameraDeviceProxy,
8};
9use fuchsia_component::client::connect_to_protocol;
10use log::*;
11use serde_json::{to_value, Value};
12
13#[derive(Debug)]
15pub struct VirtualCameraFacade {
16 camera_proxy: Option<VirtualCameraDeviceProxy>,
19}
20
21impl VirtualCameraFacade {
22 pub fn new() -> VirtualCameraFacade {
23 VirtualCameraFacade { camera_proxy: None }
24 }
25
26 pub async fn add_stream_config(&self, args: Value) -> Result<Value, Error> {
32 let config_index =
34 args["index"].as_u64().ok_or_else(|| format_err!("index not a number"))?.try_into()?;
35
36 info!("AddStreamConfig: index received {:?}", config_index);
37
38 let config_width = (args
39 .get("width")
40 .ok_or_else(|| format_err!("Expected a serde_json Value width."))?
41 .as_u64()
42 .ok_or_else(|| format_err!("Expected u64 type for width."))?
43 as u32)
44 .try_into()?;
45
46 info!("AddStreamConfig: width received {:?}", config_width);
47
48 let config_height = (args
49 .get("height")
50 .ok_or_else(|| format_err!("Expected a serde_json Value height."))?
51 .as_u64()
52 .ok_or_else(|| format_err!("Expected u64 type for height."))?
53 as u32)
54 .try_into()?;
55
56 info!("AddStreamConfig: height received {:?}", config_height);
57
58 let camera_proxy = match self.camera_proxy.as_ref() {
61 Some(proxy) => proxy.clone(),
62 None => match connect_to_protocol::<VirtualCameraDeviceMarker>() {
63 Ok(proxy) => proxy,
64 Err(e) => bail!("Failed to connect to VirtualCameraDevice FIDL service {:?}.", e),
65 },
66 };
67
68 let stream_config =
70 { StreamConfig { width: config_width, height: config_height, ..Default::default() } };
71
72 info!("Stream Config specifications {:?}", stream_config);
74 match camera_proxy.add_stream_config(config_index, &stream_config) {
75 Ok(_) => Ok(to_value(true)?),
76 Err(e) => Err(format_err!("AddStreamConfig failed with err {:?}", e)),
77 }
78 }
79
80 pub async fn add_to_device_watcher(&self) -> Result<Value, Error> {
81 let camera_proxy = match self.camera_proxy.as_ref() {
84 Some(proxy) => proxy.clone(),
85 None => match connect_to_protocol::<VirtualCameraDeviceMarker>() {
86 Ok(proxy) => proxy,
87 Err(e) => bail!("Failed to connect to VirtualCameraDevice FIDL service {:?}.", e),
88 },
89 };
90
91 info!("AddToDeviceWatcher FIDL protocol connected");
92
93 match camera_proxy.add_to_device_watcher().await? {
94 Ok(_) => Ok(to_value(true)?),
95 Err(e) => Err(format_err!("AddToDeviceWatcher failed with err {:?}", e)),
96 }
97 }
98
99 }
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use fidl::endpoints::{create_proxy, create_proxy_and_stream};
107 use fidl_fuchsia_camera_test_virtualcamera::VirtualCameraDeviceRequest;
108 use fuchsia_async as fasync;
109 use futures::prelude::*;
110 use futures::TryStreamExt;
111 use serde_json::json;
112
113 #[fasync::run_singlethreaded(test)]
116 async fn test_add_stream_config() {
117 let test_index = 0;
118 let test_width = 100;
119 let test_height = 200;
120
121 let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
122
123 let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
125
126 let facade_fut = async move {
128 assert_eq!(
129 facade
130 .add_stream_config(
131 json!({"index": test_index, "width": test_width, "height": test_height})
132 )
133 .await
134 .unwrap(),
135 to_value(true).unwrap()
136 );
137 };
138
139 let stream_fut = async move {
141 match stream.try_next().await {
142 Ok(Some(VirtualCameraDeviceRequest::AddStreamConfig { index, config, .. })) => {
143 assert_eq!(index, test_index);
144 assert_eq!(
145 config,
146 StreamConfig {
147 width: Some(test_width),
148 height: Some(test_height),
149 ..Default::default()
150 }
151 );
152 }
153 err => panic!("Err in request handler: {:?}", err),
154 }
155 };
156 future::join(facade_fut, stream_fut).await;
157 }
158
159 #[fasync::run_singlethreaded(test)]
162 async fn test_add_stream_config_with_parameter_error() {
163 let test_index = "one";
165 let test_width = "three hundred";
166 let test_height = "four hundred";
167
168 let proxy = create_proxy::<VirtualCameraDeviceMarker>();
169
170 let facade = VirtualCameraFacade { camera_proxy: Some(proxy.0) };
172
173 assert_eq!(
175 facade
176 .add_stream_config(
177 json!({"index": test_index, "width": test_width, "height": test_height})
178 )
179 .await
180 .is_ok(),
181 false
182 );
183 }
184
185 #[fasync::run_singlethreaded(test)]
188 async fn test_add_to_device_watcher() {
189 let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
190
191 let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
193
194 let facade_fut = async move {
196 assert_eq!(facade.add_to_device_watcher().await.unwrap(), to_value(true).unwrap());
197 };
198
199 let stream_fut = async move {
201 match stream.try_next().await {
202 Ok(Some(VirtualCameraDeviceRequest::AddToDeviceWatcher { responder })) => {
203 responder.send(Ok(())).unwrap();
204 }
205 err => panic!("Err in request handler: {:?}", err),
206 }
207 };
208 future::join(facade_fut, stream_fut).await;
209 }
210
211 #[fasync::run_singlethreaded(test)]
214 async fn test_add_to_device_watcher_on_error() {
215 let (proxy, mut stream) = create_proxy_and_stream::<VirtualCameraDeviceMarker>();
216
217 let facade = VirtualCameraFacade { camera_proxy: Some(proxy) };
219
220 let facade_fut = async move {
222 assert_eq!(facade.add_to_device_watcher().await.is_ok(), false);
223 };
224
225 let stream_fut = async move {
227 match stream.try_next().await {
228 Ok(Some(VirtualCameraDeviceRequest::AddToDeviceWatcher { responder })) => {
229 responder.send(
230 Err(fidl_fuchsia_camera_test_virtualcamera::
231 Error::AlreadyAddedToDeviceWatcher
232 )).unwrap();
233 }
234 err => panic!("Err in request handler: {:?}", err),
235 }
236 };
237 future::join(facade_fut, stream_fut).await;
238 }
239}