1use crate::input_reports_reader::InputReportsReader;
6use anyhow::{Context as _, Error};
7use async_utils::event::Event as AsyncEvent;
8use fidl::endpoints::ServerEnd;
9use fidl::Error as FidlError;
10use fidl_fuchsia_input_report::{
11 DeviceDescriptor, FeatureReport, InputDeviceRequest, InputDeviceRequestStream, InputReport,
12 InputReportsReaderMarker,
13};
14use fuchsia_async as fasync;
15use futures::channel::mpsc;
16use futures::{future, pin_mut, StreamExt, TryFutureExt};
17
18pub type DeviceId = u32;
19
20pub(crate) struct InputDevice {
36 report_sender: futures::channel::mpsc::UnboundedSender<InputReport>,
40
41 _input_device_task: fasync::Task<()>,
43
44 pub device_id: DeviceId,
46}
47
48impl InputDevice {
49 pub(super) fn new(
53 request_stream: InputDeviceRequestStream,
54 descriptor: DeviceDescriptor,
55 got_input_reports_reader: AsyncEvent,
56 ) -> Self {
57 let (report_sender, report_receiver) = mpsc::unbounded::<InputReport>();
58
59 let input_device_task = fasync::Task::local(Self::serve_reports(
61 request_stream,
62 descriptor,
63 report_receiver,
64 got_input_reports_reader,
65 ));
66
67 Self { report_sender, _input_device_task: input_device_task, device_id: 0 }
68 }
69
70 pub(super) fn send_input_report(&self, input_report: InputReport) -> Result<(), Error> {
72 self.report_sender
73 .unbounded_send(input_report)
74 .context("failed to send input report to reader")
75 }
76
77 #[cfg(test)]
84 pub(super) async fn flush(self) {
85 let Self { _input_device_task: input_device_task, report_sender, .. } = self;
86 std::mem::drop(report_sender); input_device_task.await
88 }
89
90 async fn serve_reports(
105 request_stream: InputDeviceRequestStream,
106 descriptor: DeviceDescriptor,
107 report_receiver: mpsc::UnboundedReceiver<InputReport>,
108 got_input_reports_reader: AsyncEvent,
109 ) {
110 let mut input_reports_reader_server_end_stream = request_stream.filter_map(|r| {
118 future::ready(Self::handle_device_request(
119 r,
120 &descriptor,
121 got_input_reports_reader.clone(),
122 ))
123 });
124
125 let input_reports_reader_fut = {
128 let reader_server_end = input_reports_reader_server_end_stream
129 .next()
130 .await
131 .unwrap_or_else(|| panic!("stream ended without a call to GetInputReportsReader"));
132 InputReportsReader { request_stream: reader_server_end.into_stream(), report_receiver }
133 .into_future()
134 };
135 pin_mut!(input_reports_reader_fut);
136
137 let input_device_server_fut = async {
140 match input_reports_reader_server_end_stream.next().await {
141 Some(_server_end) => {
142 panic!("InputDevice does not support multiple GetInputReportsReader calls")
147 }
148 None => Ok(()),
149 }
150 };
151 pin_mut!(input_device_server_fut);
152
153 future::select(
158 input_device_server_fut.and_then(|_: ()| future::pending()),
159 input_reports_reader_fut,
160 )
161 .await
162 .factor_first()
163 .0
164 .unwrap_or_else(|e| panic!("processing FIDL requests: {e}"))
165 }
166
167 fn handle_device_request(
178 request: Result<InputDeviceRequest, FidlError>,
179 descriptor: &DeviceDescriptor,
180 got_input_reports_reader: AsyncEvent,
181 ) -> Option<ServerEnd<InputReportsReaderMarker>> {
182 match request {
183 Ok(InputDeviceRequest::GetInputReportsReader { reader: reader_server_end, .. }) => {
184 let _ = got_input_reports_reader.signal();
185 Some(reader_server_end)
186 }
187 Ok(InputDeviceRequest::GetDescriptor { responder }) => {
188 match responder.send(&descriptor) {
189 Ok(()) => None,
190 Err(e) => panic!("failed to send GetDescriptor response: {e}"),
191 }
192 }
193 Ok(InputDeviceRequest::GetFeatureReport { responder }) => {
194 match responder.send(Ok(&FeatureReport::default())) {
195 Ok(()) => None,
196 Err(e) => panic!("failed to send GetFeatureReport response: {e}"),
197 }
198 }
199 Err(e) => {
200 panic!("failed to read `InputReportsReader` request: {:?}", &e);
201 }
202 _ => {
203 panic!(
204 "InputDevice::handle_device_request does not support this request: {:?}",
205 &request
206 );
207 }
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215 use fidl::endpoints;
216 use fidl_fuchsia_input_report::{DeviceDescriptor, InputDeviceMarker};
217 use fuchsia_async as fasync;
218
219 mod responds_to_get_feature_report_request {
220 use super::*;
221
222 #[fasync::run_until_stalled(test)]
223 async fn single_request_before_call_to_get_feature_report() -> Result<(), Error> {
224 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
225
226 let input_device_server_fut = Box::new(InputDevice::new(
227 request_stream,
228 DeviceDescriptor::default(),
229 AsyncEvent::new(),
230 ))
231 .flush();
232 let get_feature_report_fut = proxy.get_feature_report();
233
234 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
238 endpoints::create_proxy::<InputReportsReaderMarker>();
239 let _ = proxy.get_input_reports_reader(input_reports_reader_server_end);
240
241 std::mem::drop(proxy); let (_, get_feature_report_result) =
244 future::join(input_device_server_fut, get_feature_report_fut).await;
245 assert_eq!(
246 get_feature_report_result.context("fidl error")?,
247 Ok(FeatureReport::default())
248 );
249 Ok(())
250 }
251 }
252
253 mod responds_to_get_descriptor_request {
254 use super::utils::{make_input_device_proxy_and_struct, make_touchscreen_descriptor};
255 use super::*;
256 use assert_matches::assert_matches;
257 use futures::task::Poll;
258
259 #[fasync::run_until_stalled(test)]
260 async fn single_request_before_call_to_get_input_reports_reader() -> Result<(), Error> {
261 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
262
263 let input_device_server_fut = Box::new(InputDevice::new(
264 request_stream,
265 make_touchscreen_descriptor(),
266 AsyncEvent::new(),
267 ))
268 .flush();
269 let get_descriptor_fut = proxy.get_descriptor();
270
271 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
275 endpoints::create_proxy::<InputReportsReaderMarker>();
276 let _ = proxy.get_input_reports_reader(input_reports_reader_server_end);
277
278 std::mem::drop(proxy); let (_, get_descriptor_result) =
281 future::join(input_device_server_fut, get_descriptor_fut).await;
282 assert_eq!(get_descriptor_result.context("fidl error")?, make_touchscreen_descriptor());
283 Ok(())
284 }
285
286 #[test]
287 fn multiple_requests_before_call_to_get_input_reports_reader() -> Result<(), Error> {
288 let mut executor = fasync::TestExecutor::new();
289 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
290
291 let input_device_server_fut = Box::new(InputDevice::new(
292 request_stream,
293 make_touchscreen_descriptor(),
294 AsyncEvent::new(),
295 ))
296 .flush();
297 pin_mut!(input_device_server_fut);
298
299 let mut get_descriptor_fut = proxy.get_descriptor();
300 assert_matches!(
301 executor.run_until_stalled(&mut input_device_server_fut),
302 Poll::Pending
303 );
304 std::mem::drop(executor.run_until_stalled(&mut get_descriptor_fut));
305
306 let mut get_descriptor_fut = proxy.get_descriptor();
307 let _ = executor.run_until_stalled(&mut input_device_server_fut);
308 assert_matches!(
309 executor.run_until_stalled(&mut get_descriptor_fut),
310 Poll::Ready(Ok(_))
311 );
312
313 Ok(())
314 }
315
316 #[test]
317 fn after_call_to_get_input_reports_reader_with_report_pending() -> Result<(), Error> {
318 let mut executor = fasync::TestExecutor::new();
319 let (input_device_proxy, input_device, got_input_reports_reader) =
320 make_input_device_proxy_and_struct();
321 input_device
322 .send_input_report(InputReport {
323 event_time: None,
324 touch: None,
325 ..Default::default()
326 })
327 .context("internal error queuing input event")?;
328
329 let input_device_server_fut = input_device.flush();
330 pin_mut!(input_device_server_fut);
331
332 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
333 endpoints::create_proxy::<InputReportsReaderMarker>();
334 input_device_proxy
335 .get_input_reports_reader(input_reports_reader_server_end)
336 .context("sending get_input_reports_reader request")?;
337 assert_matches!(
338 executor.run_until_stalled(&mut input_device_server_fut),
339 Poll::Pending
340 );
341
342 let mut get_descriptor_fut = input_device_proxy.get_descriptor();
343 assert_matches!(
344 executor.run_until_stalled(&mut input_device_server_fut),
345 Poll::Pending
346 );
347 assert_matches!(executor.run_until_stalled(&mut get_descriptor_fut), Poll::Ready(_));
348
349 let mut got_input_reports_reader_fut = got_input_reports_reader.wait();
350 assert_matches!(
351 executor.run_until_stalled(&mut got_input_reports_reader_fut),
352 Poll::Ready(_)
353 );
354
355 Ok(())
356 }
357 }
358
359 mod future_resolution {
360 use super::utils::{make_input_device_proxy_and_struct, make_input_reports_reader_proxy};
361 use super::*;
362 use futures::task::Poll;
363
364 mod resolves_after_all_reports_are_sent_to_input_reports_reader {
365 use super::*;
366 use assert_matches::assert_matches;
367
368 #[test]
369 fn if_device_request_channel_was_closed() {
370 let mut executor = fasync::TestExecutor::new();
371 let (input_device_proxy, input_device, _got_input_reports_reader) =
372 make_input_device_proxy_and_struct();
373 let input_reports_reader_proxy =
374 make_input_reports_reader_proxy(&input_device_proxy);
375 input_device
376 .send_input_report(InputReport {
377 event_time: None,
378 touch: None,
379 ..Default::default()
380 })
381 .expect("queuing input report");
382
383 let _input_reports_fut = input_reports_reader_proxy.read_input_reports();
384 let input_device_fut = input_device.flush();
385 pin_mut!(input_device_fut);
386 std::mem::drop(input_device_proxy); assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Ready(()));
388 }
389
390 #[test]
391 fn even_if_device_request_channel_is_open() {
392 let mut executor = fasync::TestExecutor::new();
393 let (input_device_proxy, input_device, _got_input_reports_reader) =
394 make_input_device_proxy_and_struct();
395 let input_reports_reader_proxy =
396 make_input_reports_reader_proxy(&input_device_proxy);
397 input_device
398 .send_input_report(InputReport {
399 event_time: None,
400 touch: None,
401 ..Default::default()
402 })
403 .expect("queuing input report");
404
405 let _input_reports_fut = input_reports_reader_proxy.read_input_reports();
406 let input_device_fut = input_device.flush();
407 pin_mut!(input_device_fut);
408 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Ready(()));
409 }
410
411 #[test]
412 fn even_if_reports_was_empty_and_device_request_channel_is_open() {
413 let mut executor = fasync::TestExecutor::new();
414 let (input_device_proxy, input_device, _got_input_reports_reader) =
415 make_input_device_proxy_and_struct();
416 let input_reports_reader_proxy =
417 make_input_reports_reader_proxy(&input_device_proxy);
418 let _input_reports_fut = input_reports_reader_proxy.read_input_reports();
419 let input_device_fut = input_device.flush();
420 pin_mut!(input_device_fut);
421 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Ready(()));
422 }
423 }
424
425 mod panics_if_peer_closed_device_channel_without_calling_get_input_reports_reader {
426 use super::*;
427 use assert_matches::assert_matches;
428
429 #[test]
430 #[should_panic]
431 fn if_reports_were_available() {
432 let mut executor = fasync::TestExecutor::new();
433 let (input_device_proxy, input_device, _got_input_reports_reader) =
434 make_input_device_proxy_and_struct();
435 input_device
436 .send_input_report(InputReport {
437 event_time: None,
438 touch: None,
439 ..Default::default()
440 })
441 .expect("queuing input report");
442
443 let input_device_fut = input_device.flush();
444 pin_mut!(input_device_fut);
445 std::mem::drop(input_device_proxy);
446
447 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending);
449 }
450
451 #[test]
452 #[should_panic]
453 fn even_if_no_reports_were_available() {
454 let mut executor = fasync::TestExecutor::new();
455 let (input_device_proxy, input_device, _got_input_reports_reader) =
456 make_input_device_proxy_and_struct();
457 let input_device_fut = input_device.flush();
458 pin_mut!(input_device_fut);
459 std::mem::drop(input_device_proxy);
460
461 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending);
463 }
464 }
465
466 mod is_pending_if_peer_has_device_channel_open_and_has_not_called_get_input_reports_reader {
467 use super::*;
468 use assert_matches::assert_matches;
469
470 #[test]
471 fn if_reports_were_available() {
472 let mut executor = fasync::TestExecutor::new();
473 let (_input_device_proxy, input_device, _got_input_reports_reader) =
474 make_input_device_proxy_and_struct();
475 input_device
476 .send_input_report(InputReport {
477 event_time: None,
478 touch: None,
479 ..Default::default()
480 })
481 .expect("queuing input report");
482
483 let input_device_fut = input_device.flush();
484 pin_mut!(input_device_fut);
485 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
486 }
487
488 #[test]
489 fn even_if_no_reports_were_available() {
490 let mut executor = fasync::TestExecutor::new();
491 let (_input_device_proxy, input_device, _got_input_reports_reader) =
492 make_input_device_proxy_and_struct();
493 let input_device_fut = input_device.flush();
494 pin_mut!(input_device_fut);
495 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
496 }
497
498 #[test]
499 fn even_if_get_device_descriptor_has_been_called() {
500 let mut executor = fasync::TestExecutor::new();
501 let (input_device_proxy, input_device, _got_input_reports_reader) =
502 make_input_device_proxy_and_struct();
503 let input_device_fut = input_device.flush();
504 pin_mut!(input_device_fut);
505 let _get_descriptor_fut = input_device_proxy.get_descriptor();
506 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
507 }
508 }
509
510 mod is_pending_if_peer_has_not_read_any_reports_when_a_report_is_available {
511 use super::*;
512 use assert_matches::assert_matches;
513
514 #[test]
515 fn if_device_request_channel_is_open() {
516 let mut executor = fasync::TestExecutor::new();
517 let (input_device_proxy, input_device, _got_input_reports_reader) =
518 make_input_device_proxy_and_struct();
519 let _input_reports_reader_proxy =
520 make_input_reports_reader_proxy(&input_device_proxy);
521 input_device
522 .send_input_report(InputReport {
523 event_time: None,
524 touch: None,
525 ..Default::default()
526 })
527 .expect("queuing input report");
528
529 let input_device_fut = input_device.flush();
530 pin_mut!(input_device_fut);
531 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
532 }
533
534 #[test]
535 fn even_if_device_channel_is_closed() {
536 let mut executor = fasync::TestExecutor::new();
537 let (input_device_proxy, input_device, _got_input_reports_reader) =
538 make_input_device_proxy_and_struct();
539 let _input_reports_reader_proxy =
540 make_input_reports_reader_proxy(&input_device_proxy);
541 input_device
542 .send_input_report(InputReport {
543 event_time: None,
544 touch: None,
545 ..Default::default()
546 })
547 .expect("queuing input report");
548
549 let input_device_fut = input_device.flush();
550 std::mem::drop(input_device_proxy); pin_mut!(input_device_fut);
552 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
553 }
554 }
555
556 mod is_pending_if_peer_did_not_read_all_reports {
557 use super::*;
558 use assert_matches::assert_matches;
559 use fidl_fuchsia_input_report::MAX_DEVICE_REPORT_COUNT;
560
561 #[test]
562 fn if_device_request_channel_is_open() {
563 let mut executor = fasync::TestExecutor::new();
564 let (input_device_proxy, input_device, _got_input_reports_reader) =
565 make_input_device_proxy_and_struct();
566 let input_reports_reader_proxy =
567 make_input_reports_reader_proxy(&input_device_proxy);
568 (0..=MAX_DEVICE_REPORT_COUNT).for_each(|_| {
569 input_device
570 .send_input_report(InputReport {
571 event_time: None,
572 touch: None,
573 ..Default::default()
574 })
575 .expect("queuing input report");
576 });
577
578 let _input_reports_fut = input_reports_reader_proxy.read_input_reports();
580 let input_device_fut = input_device.flush();
581 pin_mut!(input_device_fut);
582 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
583 }
584
585 #[test]
586 fn even_if_device_request_channel_is_closed() {
587 let mut executor = fasync::TestExecutor::new();
588 let (input_device_proxy, input_device, _got_input_reports_reader) =
589 make_input_device_proxy_and_struct();
590 let input_reports_reader_proxy =
591 make_input_reports_reader_proxy(&input_device_proxy);
592 (0..=MAX_DEVICE_REPORT_COUNT).for_each(|_| {
593 input_device
594 .send_input_report(InputReport {
595 event_time: None,
596 touch: None,
597 ..Default::default()
598 })
599 .expect("queuing input report");
600 });
601
602 let _input_reports_fut = input_reports_reader_proxy.read_input_reports();
604 let input_device_fut = input_device.flush();
605 pin_mut!(input_device_fut);
606 std::mem::drop(input_device_proxy); assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
608 }
609 }
610 }
611
612 mod utils {
613 use {
614 super::*,
615 fidl_fuchsia_input_report::{
616 Axis, ContactInputDescriptor, InputDeviceProxy, InputReportsReaderProxy, Range,
617 TouchDescriptor, TouchInputDescriptor, TouchType, Unit, UnitType,
618 },
619 };
621
622 pub(super) fn make_touchscreen_descriptor() -> DeviceDescriptor {
624 DeviceDescriptor {
625 touch: Some(TouchDescriptor {
626 input: Some(TouchInputDescriptor {
627 contacts: Some(
628 std::iter::repeat(ContactInputDescriptor {
629 position_x: Some(Axis {
630 range: Range { min: -1000, max: 1000 },
631 unit: Unit { type_: UnitType::Other, exponent: 0 },
632 }),
633 position_y: Some(Axis {
634 range: Range { min: -1000, max: 1000 },
635 unit: Unit { type_: UnitType::Other, exponent: 0 },
636 }),
637 contact_width: Some(Axis {
638 range: Range { min: -1000, max: 1000 },
639 unit: Unit { type_: UnitType::Other, exponent: 0 },
640 }),
641 contact_height: Some(Axis {
642 range: Range { min: -1000, max: 1000 },
643 unit: Unit { type_: UnitType::Other, exponent: 0 },
644 }),
645 ..Default::default()
646 })
647 .take(10)
648 .collect(),
649 ),
650 max_contacts: Some(10),
651 touch_type: Some(TouchType::Touchscreen),
652 buttons: Some(vec![]),
653 ..Default::default()
654 }),
655 ..Default::default()
656 }),
657 ..Default::default()
658 }
659 }
660
661 pub(super) fn make_input_device_proxy_and_struct(
669 ) -> (InputDeviceProxy, Box<InputDevice>, AsyncEvent) {
670 let (input_device_proxy, input_device_request_stream) =
671 endpoints::create_proxy_and_stream::<InputDeviceMarker>();
672 let got_input_reports_reader = AsyncEvent::new();
673 let input_device = Box::new(InputDevice::new(
674 input_device_request_stream,
675 DeviceDescriptor::default(),
676 got_input_reports_reader.clone(),
677 ));
678 (input_device_proxy, input_device, got_input_reports_reader)
679 }
680
681 pub(super) fn make_input_reports_reader_proxy(
688 input_device_proxy: &InputDeviceProxy,
689 ) -> InputReportsReaderProxy {
690 let (input_reports_reader_proxy, input_reports_reader_server_end) =
691 endpoints::create_proxy::<InputReportsReaderMarker>();
692 input_device_proxy
693 .get_input_reports_reader(input_reports_reader_server_end)
694 .expect("sending get_input_reports_reader request");
695 input_reports_reader_proxy
696 }
697 }
698}