1#![warn(missing_docs)]
6
7use crate::modern_backend::input_reports_reader::InputReportsReaderV2;
8use crate::synthesizer;
9use crate::usages::hid_usage_to_input3_key;
10use anyhow::{Context as _, Error, format_err};
11use async_trait::async_trait;
12use fidl::Error as FidlError;
13use fidl::endpoints::ServerEnd;
14use fidl_fuchsia_input::Key;
15use fidl_fuchsia_input_report::{
16 ConsumerControlButton, ConsumerControlInputReport, ContactInputReport, DeviceDescriptor,
17 FeatureReport, InputDeviceRequest, InputDeviceRequestStream, InputReport,
18 InputReportsReaderV2Marker, KeyboardInputReport, MouseInputReport, TOUCH_MAX_CONTACTS,
19 TouchInputReport,
20};
21use fidl_fuchsia_ui_input::{KeyboardReport, Touch};
22use fuchsia_async as fasync;
23use futures::{StreamExt, TryFutureExt, future, pin_mut};
24use std::convert::TryFrom as _;
25
26pub(super) struct InputDevice {
42 report_sender: futures::channel::mpsc::UnboundedSender<InputReport>,
46
47 input_device_task: fasync::Task<Result<(), Error>>,
49}
50
51impl std::convert::From<synthesizer::MediaButton> for ConsumerControlButton {
52 fn from(synthesizer_button: synthesizer::MediaButton) -> Self {
53 match synthesizer_button {
54 synthesizer::MediaButton::VolumeUp => Self::VolumeUp,
55 synthesizer::MediaButton::VolumeDown => Self::VolumeDown,
56 synthesizer::MediaButton::MicMute => Self::MicMute,
57 synthesizer::MediaButton::FactoryReset => Self::FactoryReset,
58 synthesizer::MediaButton::Pause => Self::Pause,
59 synthesizer::MediaButton::CameraDisable => Self::CameraDisable,
60 }
61 }
62}
63
64#[async_trait(?Send)]
65impl synthesizer::InputDevice for self::InputDevice {
66 fn media_buttons(
67 &mut self,
68 pressed_buttons: Vec<synthesizer::MediaButton>,
69 time: u64,
70 ) -> Result<(), Error> {
71 self.report_sender
72 .unbounded_send(InputReport {
73 event_time: Some(i64::try_from(time).context("converting time to i64")?),
74 consumer_control: Some(ConsumerControlInputReport {
75 pressed_buttons: Some(pressed_buttons.into_iter().map(Into::into).collect()),
76 ..Default::default()
77 }),
78 ..Default::default()
79 })
80 .context("sending media button InputReport")
81 }
82
83 fn key_press(&mut self, report: KeyboardReport, time: u64) -> Result<(), Error> {
85 self.key_press_internal(report, time, Self::convert_keyboard_report_to_keys)
86 }
87
88 fn key_press_raw(&mut self, report: KeyboardReport, time: u64) -> Result<(), Error> {
89 self.key_press_internal(report, time, Self::convert_keyboard_report_to_keys_no_transform)
90 }
91
92 fn key_press_usage(&mut self, usage: Option<u32>, time: u64) -> Result<(), Error> {
94 self.key_press(KeyboardReport { pressed_keys: usage.into_iter().collect() }, time)
95 }
96
97 fn tap(&mut self, pos: Option<(u32, u32)>, time: u64) -> Result<(), Error> {
98 let fingers = pos.and_then(|(x, y)| {
99 Some(vec![Touch { finger_id: 1, x: x as i32, y: y as i32, width: 0, height: 0 }])
100 });
101 self.multi_finger_tap(fingers, time)
102 }
103
104 fn multi_finger_tap(&mut self, fingers: Option<Vec<Touch>>, time: u64) -> Result<(), Error> {
105 let num_fingers = match &fingers {
106 Some(fingers_vec) => fingers_vec.len(),
107 None => 0,
108 };
109 if num_fingers > usize::try_from(TOUCH_MAX_CONTACTS).context("usize is at least 32 bits")? {
110 return Err(format_err!(
111 "Got {} fingers, but max is {}",
112 num_fingers,
113 TOUCH_MAX_CONTACTS
114 ));
115 }
116 self.multi_finger_tap_internal(
117 TouchInputReport {
118 contacts: Some(fingers.map_or_else(Vec::new, |fingers_vec| {
119 fingers_vec
120 .into_iter()
121 .map(|finger| ContactInputReport {
122 contact_id: Some(finger.finger_id),
123 position_x: Some(i64::from(finger.x)),
124 position_y: Some(i64::from(finger.y)),
125 contact_width: Some(i64::from(finger.width)),
126 contact_height: Some(i64::from(finger.height)),
127 ..Default::default()
128 })
129 .collect()
130 })),
131 pressed_buttons: Some(vec![]),
132 ..Default::default()
133 },
134 time,
135 )
136 }
137
138 fn mouse(&mut self, report: MouseInputReport, time: u64) -> Result<(), Error> {
139 self.report_sender
140 .unbounded_send(InputReport {
141 event_time: Some(i64::try_from(time).context("converting time to i64")?),
142 mouse: Some(report),
143 ..Default::default()
144 })
145 .context("error sending mouse InputReport")
146 }
147
148 async fn flush(self: Box<Self>) -> Result<(), Error> {
149 let Self { input_device_task, report_sender } = *self;
150 std::mem::drop(report_sender); input_device_task.await
152 }
153}
154
155impl InputDevice {
156 pub(super) fn new(
160 request_stream: InputDeviceRequestStream,
161 descriptor: DeviceDescriptor,
162 ) -> Self {
163 let (report_sender, report_receiver) = futures::channel::mpsc::unbounded::<InputReport>();
164
165 let input_device_task =
167 fasync::Task::local(Self::serve_reports(request_stream, descriptor, report_receiver));
168
169 Self { report_sender, input_device_task }
170 }
171
172 async fn serve_reports(
192 request_stream: InputDeviceRequestStream,
193 descriptor: DeviceDescriptor,
194 report_receiver: futures::channel::mpsc::UnboundedReceiver<InputReport>,
195 ) -> Result<(), Error> {
196 let mut input_reports_reader_server_end_stream = request_stream
199 .filter_map(|r| future::ready(Self::handle_device_request(r, &descriptor)));
200 let input_reports_reader_fut = {
201 let (reader_server_end, max_unacknowledged_reports) =
202 input_reports_reader_server_end_stream
203 .next()
204 .await
205 .ok_or_else(|| {
206 format_err!("stream ended without a call to GetInputReportsReaderV2")
207 })?
208 .context("handling InputDeviceRequest")?;
209 InputReportsReaderV2 {
210 request_stream: reader_server_end.into_stream(),
211 report_receiver,
212 max_unacknowledged_reports,
213 }
214 .into_future()
215 };
216 pin_mut!(input_reports_reader_fut);
217
218 let input_device_server_fut = async {
221 match input_reports_reader_server_end_stream.next().await {
222 Some(Ok(_server_end)) => {
223 Err(format_err!(
228 "InputDevice does not support multiple GetInputReportsReaderV2 calls"
229 ))
230 }
231 Some(Err(e)) => Err(e.context("handling InputDeviceRequest")),
232 None => Ok(()),
233 }
234 };
235 pin_mut!(input_device_server_fut);
236
237 future::select(
242 input_device_server_fut.and_then(|_: ()| future::pending()),
243 input_reports_reader_fut,
244 )
245 .await
246 .factor_first()
247 .0
248 }
249
250 fn key_press_internal(
253 &mut self,
254 report: KeyboardReport,
255 time: u64,
256 transform: fn(r: &KeyboardReport) -> Result<Vec<Key>, Error>,
257 ) -> Result<(), Error> {
258 self.report_sender
259 .unbounded_send(InputReport {
260 event_time: Some(i64::try_from(time).context("converting time to i64")?),
261 keyboard: Some(KeyboardInputReport {
262 pressed_keys3: Some(transform(&report)?),
263 ..Default::default()
264 }),
265 ..Default::default()
266 })
267 .context("sending key press InputReport")
268 }
269
270 fn multi_finger_tap_internal(
271 &mut self,
272 touch: TouchInputReport,
273 time: u64,
274 ) -> Result<(), Error> {
275 self.report_sender
276 .unbounded_send(InputReport {
277 event_time: Some(i64::try_from(time).context("converting time to i64")?),
278 touch: Some(touch),
279 ..Default::default()
280 })
281 .context("sending touch InputReport")
282 }
283
284 fn handle_device_request(
291 request: Result<InputDeviceRequest, FidlError>,
292 descriptor: &DeviceDescriptor,
293 ) -> Option<Result<(ServerEnd<InputReportsReaderV2Marker>, u16), Error>> {
294 match request {
295 Ok(InputDeviceRequest::GetInputReportsReaderV2 {
296 reader: reader_server_end,
297 max_unacknowledged_reports_limit,
298 responder,
299 }) => {
300 let max_unacknowledged_reports = max_unacknowledged_reports_limit.max(1);
301 if let Err(e) = responder.send(max_unacknowledged_reports) {
302 return Some(Err(
303 anyhow::Error::from(e).context("sending GetInputReportsReaderV2 response")
304 ));
305 }
306 Some(Ok((reader_server_end, max_unacknowledged_reports)))
307 }
308 Ok(InputDeviceRequest::GetDescriptor { responder }) => {
309 match responder.send(&descriptor) {
310 Ok(()) => None,
311 Err(e) => {
312 Some(Err(anyhow::Error::from(e).context("sending GetDescriptor response")))
313 }
314 }
315 }
316 Ok(InputDeviceRequest::GetFeatureReport { responder }) => {
317 match responder.send(Ok(&FeatureReport::default())) {
318 Ok(()) => None,
319 Err(e) => Some(Err(
320 anyhow::Error::from(e).context("sending GetFeatureReport response")
321 )),
322 }
323 }
324 Err(e) => {
325 panic!("InputDevice got an error while reading request: {:?}", e);
332 }
333 _ => {
334 panic!(
336 "InputDevice::handle_device_request does not support this request: {:?}",
337 request
338 );
339 }
340 }
341 }
342
343 fn convert_keyboard_report_to_keys(report: &KeyboardReport) -> Result<Vec<Key>, Error> {
344 report
345 .pressed_keys
346 .iter()
347 .map(|&usage| {
348 hid_usage_to_input3_key(usage as u16)
349 .ok_or_else(|| format_err!("no Key for usage {:?}", usage))
350 })
351 .collect()
352 }
353
354 fn convert_keyboard_report_to_keys_no_transform(
363 report: &KeyboardReport,
364 ) -> Result<Vec<Key>, Error> {
365 report
366 .pressed_keys
367 .iter()
368 .map(|&usage| {
369 Key::from_primitive(usage)
370 .ok_or_else(|| anyhow::anyhow!("could not convert to input::Key: {}", usage))
371 })
372 .collect()
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use super::synthesizer::InputDevice as _;
379 use super::*;
380 use fidl::endpoints;
381 use fidl_fuchsia_input_report::{
382 DeviceDescriptor, InputDeviceMarker, KeyboardDescriptor, KeyboardInputDescriptor,
383 };
384 use fuchsia_async as fasync;
385
386 const DEFAULT_REPORT_TIMESTAMP: u64 = 0;
387
388 mod responds_to_get_feature_report_request {
389 use super::*;
390
391 #[fasync::run_until_stalled(test)]
392 async fn single_request_before_call_to_get_feature_report() -> Result<(), Error> {
393 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
394 let input_device_server_fut =
395 Box::new(InputDevice::new(request_stream, DeviceDescriptor::default())).flush();
396 let get_feature_report_fut = proxy.get_feature_report();
397 std::mem::drop(proxy); let (_, get_feature_report_result) =
400 future::join(input_device_server_fut, get_feature_report_fut).await;
401 assert_eq!(
402 get_feature_report_result.context("fidl error")?,
403 Ok(FeatureReport::default())
404 );
405 Ok(())
406 }
407 }
408
409 mod responds_to_get_descriptor_request {
410 use super::utils::{make_input_device_proxy_and_struct, make_keyboard_descriptor};
411 use super::*;
412 use assert_matches::assert_matches;
413 use futures::task::Poll;
414
415 #[fasync::run_until_stalled(test)]
416 async fn single_request_before_call_to_get_input_reports_reader() -> Result<(), Error> {
417 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
418 let input_device_server_fut =
419 Box::new(InputDevice::new(request_stream, make_keyboard_descriptor(vec![Key::A])))
420 .flush();
421 let get_descriptor_fut = proxy.get_descriptor();
422 std::mem::drop(proxy); let (_, get_descriptor_result) =
425 future::join(input_device_server_fut, get_descriptor_fut).await;
426 assert_eq!(
427 get_descriptor_result.context("fidl error")?,
428 make_keyboard_descriptor(vec![Key::A])
429 );
430 Ok(())
431 }
432
433 #[test]
434 fn multiple_requests_before_call_to_get_input_reports_reader() -> Result<(), Error> {
435 let mut executor = fasync::TestExecutor::new();
436 let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
437 let mut input_device_server_fut =
438 Box::new(InputDevice::new(request_stream, make_keyboard_descriptor(vec![Key::A])))
439 .flush();
440
441 let mut get_descriptor_fut = proxy.get_descriptor();
442 assert_matches!(
443 executor.run_until_stalled(&mut input_device_server_fut),
444 Poll::Pending
445 );
446 std::mem::drop(executor.run_until_stalled(&mut get_descriptor_fut));
447
448 let mut get_descriptor_fut = proxy.get_descriptor();
449 let _ = executor.run_until_stalled(&mut input_device_server_fut);
450 assert_matches!(
451 executor.run_until_stalled(&mut get_descriptor_fut),
452 Poll::Ready(Ok(_))
453 );
454
455 Ok(())
456 }
457
458 #[test]
459 fn after_call_to_get_input_reports_reader_with_report_pending() -> Result<(), Error> {
460 let mut executor = fasync::TestExecutor::new();
461 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
462 for _ in 0..2 {
463 input_device
464 .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
465 .context("internal error queuing input event")?;
466 }
467
468 let input_device_server_fut = input_device.flush();
469 pin_mut!(input_device_server_fut);
470
471 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
472 endpoints::create_proxy::<InputReportsReaderV2Marker>();
473
474 const MAX_UNACKNOWLEDGED_REPORTS_LIMIT: u16 = 1;
475 let _ = input_device_proxy.get_input_reports_reader_v2(
476 input_reports_reader_server_end,
477 MAX_UNACKNOWLEDGED_REPORTS_LIMIT,
478 );
479 assert_matches!(
480 executor.run_until_stalled(&mut input_device_server_fut),
481 Poll::Pending
482 );
483
484 let mut get_descriptor_fut = input_device_proxy.get_descriptor();
485 assert_matches!(
486 executor.run_until_stalled(&mut input_device_server_fut),
487 Poll::Pending
488 );
489 assert_matches!(executor.run_until_stalled(&mut get_descriptor_fut), Poll::Ready(_));
490 Ok(())
491 }
492 }
493
494 mod report_contents {
495 use super::utils::{get_input_reports, make_input_device_proxy_and_struct};
496 use super::*;
497 use crate::usages::Usages;
498 use assert_matches::assert_matches;
499 use std::convert::TryInto as _;
500
501 #[fasync::run_until_stalled(test)]
502 async fn media_buttons_generates_empty_consumer_controls_input_report() -> Result<(), Error>
503 {
504 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
505 input_device.media_buttons(vec![], DEFAULT_REPORT_TIMESTAMP)?;
506
507 let input_reports = get_input_reports(input_device, input_device_proxy).await;
508 assert_eq!(
509 input_reports.as_slice(),
510 [InputReport {
511 event_time: Some(
512 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
513 ),
514 consumer_control: Some(ConsumerControlInputReport {
515 pressed_buttons: Some(vec![]),
516 ..Default::default()
517 }),
518 ..Default::default()
519 }]
520 );
521 Ok(())
522 }
523
524 #[fasync::run_until_stalled(test)]
525 async fn media_buttons_generates_full_consumer_controls_input_report() -> Result<(), Error>
526 {
527 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
528 input_device.media_buttons(
529 vec![
530 synthesizer::MediaButton::VolumeUp,
531 synthesizer::MediaButton::VolumeDown,
532 synthesizer::MediaButton::MicMute,
533 synthesizer::MediaButton::FactoryReset,
534 synthesizer::MediaButton::Pause,
535 synthesizer::MediaButton::CameraDisable,
536 ],
537 DEFAULT_REPORT_TIMESTAMP,
538 )?;
539
540 let input_reports = get_input_reports(input_device, input_device_proxy).await;
541 assert_eq!(
542 input_reports.as_slice(),
543 [InputReport {
544 event_time: Some(
545 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
546 ),
547 consumer_control: Some(ConsumerControlInputReport {
548 pressed_buttons: Some(vec![
549 ConsumerControlButton::VolumeUp,
550 ConsumerControlButton::VolumeDown,
551 ConsumerControlButton::MicMute,
552 ConsumerControlButton::FactoryReset,
553 ConsumerControlButton::Pause,
554 ConsumerControlButton::CameraDisable,
555 ]),
556 ..Default::default()
557 }),
558 ..Default::default()
559 }]
560 );
561 Ok(())
562 }
563
564 #[fasync::run_until_stalled(test)]
565 async fn media_buttons_generates_partial_consumer_controls_input_report()
566 -> Result<(), Error> {
567 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
568 input_device.media_buttons(
569 vec![
570 synthesizer::MediaButton::VolumeUp,
571 synthesizer::MediaButton::MicMute,
572 synthesizer::MediaButton::Pause,
573 ],
574 DEFAULT_REPORT_TIMESTAMP,
575 )?;
576
577 let input_reports = get_input_reports(input_device, input_device_proxy).await;
578 assert_eq!(
579 input_reports.as_slice(),
580 [InputReport {
581 event_time: Some(
582 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
583 ),
584 consumer_control: Some(ConsumerControlInputReport {
585 pressed_buttons: Some(vec![
586 ConsumerControlButton::VolumeUp,
587 ConsumerControlButton::MicMute,
588 ConsumerControlButton::Pause,
589 ]),
590 ..Default::default()
591 }),
592 ..Default::default()
593 }]
594 );
595 Ok(())
596 }
597
598 #[fasync::run_until_stalled(test)]
599 async fn key_press_generates_expected_keyboard_input_report() -> Result<(), Error> {
600 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
601 input_device.key_press(
602 KeyboardReport {
603 pressed_keys: vec![Usages::HidUsageKeyA as u32, Usages::HidUsageKeyB as u32],
604 },
605 DEFAULT_REPORT_TIMESTAMP,
606 )?;
607
608 let input_reports = get_input_reports(input_device, input_device_proxy).await;
609 assert_eq!(
610 input_reports.as_slice(),
611 [InputReport {
612 event_time: Some(
613 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
614 ),
615 keyboard: Some(KeyboardInputReport {
616 pressed_keys3: Some(vec![Key::A, Key::B]),
617 ..Default::default()
618 }),
619 ..Default::default()
620 }]
621 );
622 Ok(())
623 }
624
625 #[fasync::run_until_stalled(test)]
626 async fn key_press_usage_generates_expected_keyboard_input_report_for_some()
627 -> Result<(), Error> {
628 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
629 input_device
630 .key_press_usage(Some(Usages::HidUsageKeyA as u32), DEFAULT_REPORT_TIMESTAMP)?;
631
632 let input_reports = get_input_reports(input_device, input_device_proxy).await;
633 assert_eq!(
634 input_reports.as_slice(),
635 [InputReport {
636 event_time: Some(
637 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
638 ),
639 keyboard: Some(KeyboardInputReport {
640 pressed_keys3: Some(vec![Key::A]),
641 ..Default::default()
642 }),
643 ..Default::default()
644 }]
645 );
646 Ok(())
647 }
648
649 #[fasync::run_until_stalled(test)]
650 async fn key_press_usage_generates_expected_keyboard_input_report_for_none()
651 -> Result<(), Error> {
652 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
653 input_device.key_press_usage(None, DEFAULT_REPORT_TIMESTAMP)?;
654
655 let input_reports = get_input_reports(input_device, input_device_proxy).await;
656 assert_eq!(
657 input_reports.as_slice(),
658 [InputReport {
659 event_time: Some(
660 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
661 ),
662 keyboard: Some(KeyboardInputReport {
663 pressed_keys3: Some(vec![]),
664 ..Default::default()
665 }),
666 ..Default::default()
667 }]
668 );
669 Ok(())
670 }
671
672 #[fasync::run_until_stalled(test)]
673 async fn key_press_returns_error_if_usage_cannot_be_mapped_to_key() {
674 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
675 assert_matches!(
676 input_device.key_press(
677 KeyboardReport { pressed_keys: vec![0xffff_ffff] },
678 DEFAULT_REPORT_TIMESTAMP
679 ),
680 Err(_)
681 );
682 }
683
684 #[fasync::run_until_stalled(test)]
685 async fn key_press_usage_returns_error_if_usage_cannot_be_mapped_to_key() {
686 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
687 assert_matches!(
688 input_device.key_press_usage(Some(0xffff_ffff), DEFAULT_REPORT_TIMESTAMP),
689 Err(_)
690 );
691 }
692
693 #[fasync::run_until_stalled(test)]
694 async fn key_events_generates_expected_keyboard_response() -> Result<(), Error> {
695 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
696 input_device.key_press_raw(
697 KeyboardReport {
698 pressed_keys: vec![Key::A.into_primitive(), Key::B.into_primitive()],
699 },
700 DEFAULT_REPORT_TIMESTAMP,
701 )?;
702
703 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
704 assert_eq!(
705 input_reports.as_slice(),
706 [InputReport {
707 event_time: Some(
708 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
709 ),
710 keyboard: Some(KeyboardInputReport {
711 pressed_keys3: Some(vec![Key::A, Key::B]),
712 ..Default::default()
713 }),
714 ..Default::default()
715 }]
716 );
717 Ok(())
718 }
719
720 #[fasync::run_until_stalled(test)]
721 async fn tap_generates_expected_report_for_some() -> Result<(), Error> {
722 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
723 input_device.tap(Some((10, 20)), DEFAULT_REPORT_TIMESTAMP)?;
724
725 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
726 assert_eq!(
727 input_reports.as_slice(),
728 [InputReport {
729 event_time: Some(
730 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
731 ),
732 touch: Some(TouchInputReport {
733 contacts: Some(vec![ContactInputReport {
734 contact_id: Some(1),
735 position_x: Some(10),
736 position_y: Some(20),
737 pressure: None,
738 contact_width: Some(0),
739 contact_height: Some(0),
740 ..Default::default()
741 }]),
742 pressed_buttons: Some(vec![]),
743 ..Default::default()
744 }),
745 ..Default::default()
746 }]
747 );
748 Ok(())
749 }
750
751 #[fasync::run_until_stalled(test)]
752 async fn tap_generates_expected_report_for_none() -> Result<(), Error> {
753 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
754 input_device.tap(None, DEFAULT_REPORT_TIMESTAMP)?;
755
756 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
757 assert_eq!(
758 input_reports.as_slice(),
759 [InputReport {
760 event_time: Some(
761 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
762 ),
763 touch: Some(TouchInputReport {
764 contacts: Some(vec![]),
765 pressed_buttons: Some(vec![]),
766 ..Default::default()
767 }),
768 ..Default::default()
769 }]
770 );
771 Ok(())
772 }
773
774 #[fasync::run_until_stalled(test)]
775 async fn multi_finger_tap_generates_report_for_single_finger() -> Result<(), Error> {
776 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
777 input_device.multi_finger_tap(
778 Some(vec![Touch { finger_id: 5, x: 10, y: 20, width: 100, height: 200 }]),
779 DEFAULT_REPORT_TIMESTAMP,
780 )?;
781
782 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
783 assert_eq!(
784 input_reports.as_slice(),
785 [InputReport {
786 event_time: Some(
787 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
788 ),
789 touch: Some(TouchInputReport {
790 contacts: Some(vec![ContactInputReport {
791 contact_id: Some(5),
792 position_x: Some(10),
793 position_y: Some(20),
794 pressure: None,
795 contact_width: Some(100),
796 contact_height: Some(200),
797 ..Default::default()
798 }]),
799 pressed_buttons: Some(vec![]),
800 ..Default::default()
801 }),
802 ..Default::default()
803 }]
804 );
805 Ok(())
806 }
807
808 #[fasync::run_until_stalled(test)]
809 async fn multi_finger_tap_generates_expected_report_for_two_fingers() -> Result<(), Error> {
810 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
811 input_device.multi_finger_tap(
812 Some(vec![
813 Touch { finger_id: 5, x: 10, y: 20, width: 100, height: 200 },
814 Touch { finger_id: 0, x: 30, y: 40, width: 300, height: 400 },
815 ]),
816 DEFAULT_REPORT_TIMESTAMP,
817 )?;
818
819 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
820 assert_eq!(
821 input_reports.as_slice(),
822 [InputReport {
823 event_time: Some(
824 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
825 ),
826 touch: Some(TouchInputReport {
827 contacts: Some(vec![
828 ContactInputReport {
829 contact_id: Some(5),
830 position_x: Some(10),
831 position_y: Some(20),
832 pressure: None,
833 contact_width: Some(100),
834 contact_height: Some(200),
835 ..Default::default()
836 },
837 ContactInputReport {
838 contact_id: Some(0),
839 position_x: Some(30),
840 position_y: Some(40),
841 pressure: None,
842 contact_width: Some(300),
843 contact_height: Some(400),
844 ..Default::default()
845 }
846 ]),
847 pressed_buttons: Some(vec![]),
848 ..Default::default()
849 }),
850 ..Default::default()
851 }]
852 );
853 Ok(())
854 }
855
856 #[fasync::run_until_stalled(test)]
857 async fn multi_finger_tap_generates_expected_report_for_zero_fingers() -> Result<(), Error>
858 {
859 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
860 input_device.multi_finger_tap(Some(vec![]), DEFAULT_REPORT_TIMESTAMP)?;
861
862 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
863 assert_eq!(
864 input_reports.as_slice(),
865 [InputReport {
866 event_time: Some(
867 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
868 ),
869 touch: Some(TouchInputReport {
870 contacts: Some(vec![]),
871 pressed_buttons: Some(vec![]),
872 ..Default::default()
873 }),
874 ..Default::default()
875 }]
876 );
877 Ok(())
878 }
879
880 #[fasync::run_until_stalled(test)]
881 async fn multi_finger_tap_generates_expected_report_for_none() -> Result<(), Error> {
882 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
883 input_device.multi_finger_tap(None, DEFAULT_REPORT_TIMESTAMP)?;
884
885 let input_reports = get_input_reports(input_device, _input_device_proxy).await;
886 assert_eq!(
887 input_reports.as_slice(),
888 [InputReport {
889 event_time: Some(
890 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
891 ),
892 touch: Some(TouchInputReport {
893 contacts: Some(vec![]),
894 pressed_buttons: Some(vec![]),
895 ..Default::default()
896 }),
897 ..Default::default()
898 }]
899 );
900 Ok(())
901 }
902
903 #[fasync::run_until_stalled(test)]
904 async fn multi_finger_tap_returns_error_when_num_fingers_is_to_large() {
905 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
906 assert_matches!(
907 input_device.multi_finger_tap(
908 Some(
909 (0..=TOUCH_MAX_CONTACTS)
910 .map(|i| Touch {
911 finger_id: i,
912 x: i as i32,
913 y: i as i32,
914 width: i,
915 height: i
916 })
917 .collect(),
918 ),
919 DEFAULT_REPORT_TIMESTAMP,
920 ),
921 Err(_)
922 );
923 }
924
925 #[fasync::run_until_stalled(test)]
926 async fn mouse_generates_empty_mouse_input_report() -> Result<(), Error> {
927 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
928 input_device.mouse(MouseInputReport::default(), DEFAULT_REPORT_TIMESTAMP)?;
929
930 let input_reports = get_input_reports(input_device, input_device_proxy).await;
931 assert_eq!(
932 input_reports.as_slice(),
933 [InputReport {
934 event_time: Some(
935 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
936 ),
937 mouse: Some(MouseInputReport::default()),
938 ..Default::default()
939 }]
940 );
941 Ok(())
942 }
943
944 #[fasync::run_until_stalled(test)]
945 async fn mouse_generates_full_mouse_input_report() -> Result<(), Error> {
946 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
947 input_device.mouse(
948 MouseInputReport {
949 movement_x: Some(10),
950 movement_y: Some(15),
951 pressed_buttons: Some(vec![1, 2, 3]),
952 scroll_v: Some(1),
953 scroll_h: Some(-1),
954 ..Default::default()
955 },
956 DEFAULT_REPORT_TIMESTAMP,
957 )?;
958
959 let input_reports = get_input_reports(input_device, input_device_proxy).await;
960 assert_eq!(
961 input_reports.as_slice(),
962 [InputReport {
963 event_time: Some(
964 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
965 ),
966 mouse: Some(MouseInputReport {
967 movement_x: Some(10),
968 movement_y: Some(15),
969 pressed_buttons: Some(vec![1, 2, 3]),
970 scroll_v: Some(1),
971 scroll_h: Some(-1),
972 ..Default::default()
973 }),
974 ..Default::default()
975 }]
976 );
977 Ok(())
978 }
979
980 #[fasync::run_until_stalled(test)]
981 async fn mouse_generates_partial_mouse_input_report() -> Result<(), Error> {
982 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
983 input_device.mouse(
984 MouseInputReport {
985 movement_x: Some(10),
986 movement_y: Some(15),
987 pressed_buttons: Some(vec![]),
988 ..Default::default()
989 },
990 DEFAULT_REPORT_TIMESTAMP,
991 )?;
992
993 let input_reports = get_input_reports(input_device, input_device_proxy).await;
994 assert_eq!(
995 input_reports.as_slice(),
996 [InputReport {
997 event_time: Some(
998 DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
999 ),
1000 mouse: Some(MouseInputReport {
1001 movement_x: Some(10),
1002 movement_y: Some(15),
1003 pressed_buttons: Some(vec![]),
1004 ..Default::default()
1005 }),
1006 ..Default::default()
1007 }]
1008 );
1009 Ok(())
1010 }
1011 }
1012
1013 mod future_resolution {
1014 use super::utils::{make_input_device_proxy_and_struct, make_input_reports_reader_proxy};
1015 use super::*;
1016 use futures::task::Poll;
1017
1018 mod yields_ok_after_all_reports_are_sent_to_input_reports_reader {
1019 use super::*;
1020 use assert_matches::assert_matches;
1021
1022 #[test]
1023 fn if_device_request_channel_was_closed() {
1024 let mut executor = fasync::TestExecutor::new();
1025 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1026 let _input_reports_reader_proxy =
1027 make_input_reports_reader_proxy(&input_device_proxy);
1028 input_device
1029 .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1030 .expect("queuing input report");
1031
1032 let mut input_device_fut = input_device.flush();
1033 std::mem::drop(input_device_proxy); assert_matches!(
1035 executor.run_until_stalled(&mut input_device_fut),
1036 Poll::Ready(Ok(()))
1037 );
1038 }
1039
1040 #[test]
1041 fn even_if_device_request_channel_is_open() {
1042 let mut executor = fasync::TestExecutor::new();
1043 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1044 let _input_reports_reader_proxy =
1045 make_input_reports_reader_proxy(&input_device_proxy);
1046 input_device
1047 .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1048 .expect("queuing input report");
1049
1050 let mut input_device_fut = input_device.flush();
1051 assert_matches!(
1052 executor.run_until_stalled(&mut input_device_fut),
1053 Poll::Ready(Ok(()))
1054 );
1055 }
1056
1057 #[test]
1058 fn even_if_reports_was_empty_and_device_request_channel_is_open() {
1059 let mut executor = fasync::TestExecutor::new();
1060 let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1061 let _input_reports_reader_proxy =
1062 make_input_reports_reader_proxy(&input_device_proxy);
1063 let mut input_device_fut = input_device.flush();
1064 assert_matches!(
1065 executor.run_until_stalled(&mut input_device_fut),
1066 Poll::Ready(Ok(()))
1067 );
1068 }
1069 }
1070
1071 mod yields_err_if_peer_closed_device_channel_without_calling_get_input_reports_reader {
1072 use super::*;
1073 use assert_matches::assert_matches;
1074
1075 #[test]
1076 fn if_reports_were_available() {
1077 let mut executor = fasync::TestExecutor::new();
1078 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1079 input_device
1080 .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1081 .expect("queuing input report");
1082
1083 let mut input_device_fut = input_device.flush();
1084 std::mem::drop(input_device_proxy);
1085 assert_matches!(
1086 executor.run_until_stalled(&mut input_device_fut),
1087 Poll::Ready(Err(_))
1088 )
1089 }
1090
1091 #[test]
1092 fn even_if_no_reports_were_available() {
1093 let mut executor = fasync::TestExecutor::new();
1094 let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1095 let mut input_device_fut = input_device.flush();
1096 std::mem::drop(input_device_proxy);
1097 assert_matches!(
1098 executor.run_until_stalled(&mut input_device_fut),
1099 Poll::Ready(Err(_))
1100 )
1101 }
1102 }
1103
1104 mod is_pending_if_peer_has_device_channel_open_and_has_not_called_get_input_reports_reader {
1105 use super::*;
1106 use assert_matches::assert_matches;
1107
1108 #[test]
1109 fn if_reports_were_available() {
1110 let mut executor = fasync::TestExecutor::new();
1111 let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1112 input_device
1113 .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1114 .expect("queuing input report");
1115
1116 let mut input_device_fut = input_device.flush();
1117 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1118 }
1119
1120 #[test]
1121 fn even_if_no_reports_were_available() {
1122 let mut executor = fasync::TestExecutor::new();
1123 let (_input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1124 let mut input_device_fut = input_device.flush();
1125 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1126 }
1127
1128 #[test]
1129 fn even_if_get_device_descriptor_has_been_called() {
1130 let mut executor = fasync::TestExecutor::new();
1131 let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1132 let mut input_device_fut = input_device.flush();
1133 let _get_descriptor_fut = input_device_proxy.get_descriptor();
1134 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1135 }
1136 }
1137
1138 mod is_pending_if_unacknowledged_reports_reach_limit {
1139 use super::utils::make_input_reports_reader_proxy_with_limit;
1140 use super::*;
1141 use assert_matches::assert_matches;
1142
1143 #[test]
1144 fn if_device_request_channel_is_open() {
1145 let mut executor = fasync::TestExecutor::new();
1146 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1147 let _input_reports_reader_proxy =
1148 make_input_reports_reader_proxy_with_limit(&input_device_proxy, 1);
1149 for _ in 0..2 {
1150 input_device
1151 .key_press(
1152 KeyboardReport { pressed_keys: vec![] },
1153 DEFAULT_REPORT_TIMESTAMP,
1154 )
1155 .expect("queuing input report");
1156 }
1157
1158 let mut input_device_fut = input_device.flush();
1159 assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1160 }
1161
1162 #[test]
1163 fn even_if_device_request_channel_is_closed() {
1164 let mut executor = fasync::TestExecutor::new();
1165 let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1166 let _input_reports_reader_proxy =
1167 make_input_reports_reader_proxy_with_limit(&input_device_proxy, 1);
1168 for _ in 0..2 {
1169 input_device
1170 .key_press(
1171 KeyboardReport { pressed_keys: vec![] },
1172 DEFAULT_REPORT_TIMESTAMP,
1173 )
1174 .expect("queuing input report");
1175 }
1176
1177 let mut input_device_fut = input_device.flush();
1178 std::mem::drop(input_device_proxy); assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1180 }
1181 }
1182 }
1183
1184 mod unsupported_use_cases {
1187 use super::utils::make_input_device_proxy_and_struct;
1188 use super::*;
1189 use assert_matches::assert_matches;
1190
1191 #[fasync::run_until_stalled(test)]
1192 async fn multiple_get_input_reports_reader_requests_yield_error() -> Result<(), Error> {
1193 let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1194
1195 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
1196 endpoints::create_proxy::<InputReportsReaderV2Marker>();
1197 let _ = input_device_proxy
1198 .get_input_reports_reader_v2(input_reports_reader_server_end, 120);
1199
1200 let (_input_reports_reader_proxy, input_reports_reader_server_end) =
1201 endpoints::create_proxy::<InputReportsReaderV2Marker>();
1202 let _ = input_device_proxy
1203 .get_input_reports_reader_v2(input_reports_reader_server_end, 120);
1204
1205 let input_device_fut = input_device.flush();
1206 assert_matches!(input_device_fut.await, Err(_));
1207 Ok(())
1208 }
1209 }
1210
1211 mod utils {
1212 use super::*;
1213 use fidl_fuchsia_input_report::{
1214 InputDeviceProxy, InputReportsReaderV2Event, InputReportsReaderV2Proxy,
1215 };
1216
1217 pub(super) fn make_keyboard_descriptor(keys: Vec<Key>) -> DeviceDescriptor {
1220 DeviceDescriptor {
1221 keyboard: Some(KeyboardDescriptor {
1222 input: Some(KeyboardInputDescriptor {
1223 keys3: Some(keys),
1224 ..Default::default()
1225 }),
1226 ..Default::default()
1227 }),
1228 ..Default::default()
1229 }
1230 }
1231
1232 pub(super) fn make_input_device_proxy_and_struct() -> (InputDeviceProxy, Box<InputDevice>) {
1240 let (input_device_proxy, input_device_request_stream) =
1241 endpoints::create_proxy_and_stream::<InputDeviceMarker>();
1242 let input_device = Box::new(InputDevice::new(
1243 input_device_request_stream,
1244 DeviceDescriptor::default(),
1245 ));
1246 (input_device_proxy, input_device)
1247 }
1248
1249 pub(super) fn make_input_reports_reader_proxy(
1256 input_device_proxy: &InputDeviceProxy,
1257 ) -> InputReportsReaderV2Proxy {
1258 make_input_reports_reader_proxy_with_limit(input_device_proxy, 120)
1259 }
1260
1261 pub(super) fn make_input_reports_reader_proxy_with_limit(
1262 input_device_proxy: &InputDeviceProxy,
1263 limit: u16,
1264 ) -> InputReportsReaderV2Proxy {
1265 let (input_reports_reader_proxy, input_reports_reader_server_end) =
1266 endpoints::create_proxy::<InputReportsReaderV2Marker>();
1267 let _ = input_device_proxy
1268 .get_input_reports_reader_v2(input_reports_reader_server_end, limit);
1269 input_reports_reader_proxy
1270 }
1271
1272 pub(super) async fn get_input_reports(
1279 input_device: Box<InputDevice>,
1280 input_device_proxy: InputDeviceProxy,
1281 ) -> Vec<InputReport> {
1282 let input_reports_reader_proxy = make_input_reports_reader_proxy(&input_device_proxy);
1283 let mut event_stream = input_reports_reader_proxy.take_event_stream();
1284 let input_device_server_fut = input_device.flush();
1285 let read_reports_fut = async {
1286 let mut reports = Vec::new();
1287 while let Some(Ok(InputReportsReaderV2Event::OnInputReports {
1288 reports: batch,
1289 last_report_stamp,
1290 })) = event_stream.next().await
1291 {
1292 let _ = input_reports_reader_proxy.acknowledge_reports(last_report_stamp);
1293 reports.extend(batch);
1294 }
1295 reports
1296 };
1297 std::mem::drop(input_device_proxy); let (flush_res, reports) =
1299 future::join(input_device_server_fut, read_reports_fut).await;
1300 flush_res.expect("flush error");
1301 reports
1302 }
1303 }
1304}