1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{InputHandler, InputHandlerStatus};
8use crate::utils::{CursorMessage, Position, Size};
9use crate::{input_device, metrics, mouse_binding};
10use anyhow::{anyhow, Context, Error, Result};
11use async_trait::async_trait;
12use async_utils::hanging_get::client::HangingGetStream;
13use fidl::endpoints::create_proxy;
14use fidl_fuchsia_input_report::Range;
15use fuchsia_component::client::connect_to_protocol;
16use fuchsia_inspect::health::Reporter;
17use futures::channel::mpsc::Sender;
18use futures::stream::StreamExt;
19use futures::SinkExt;
20use metrics_registry::*;
21use std::cell::{Ref, RefCell, RefMut};
22use std::collections::HashMap;
23use std::rc::Rc;
24use {
25 fidl_fuchsia_ui_pointerinjector as pointerinjector,
26 fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config,
27};
28
29const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
37
38pub struct MouseInjectorHandler {
41 mutable_state: RefCell<MutableState>,
43
44 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
47
48 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
51
52 max_position: Position,
55
56 injector_registry_proxy: pointerinjector::RegistryProxy,
58
59 configuration_proxy: pointerinjector_config::SetupProxy,
61
62 pub inspect_status: InputHandlerStatus,
64
65 metrics_logger: metrics::MetricsLogger,
66}
67
68struct MutableState {
69 viewport: Option<pointerinjector::Viewport>,
72
73 injectors: HashMap<u32, pointerinjector::DeviceProxy>,
75
76 current_position: Position,
78
79 cursor_message_sender: Sender<CursorMessage>,
81}
82
83#[async_trait(?Send)]
84impl InputHandler for MouseInjectorHandler {
85 async fn handle_input_event(
86 self: Rc<Self>,
87 mut input_event: input_device::InputEvent,
88 ) -> Vec<input_device::InputEvent> {
89 match input_event {
90 input_device::InputEvent {
91 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
92 device_descriptor:
93 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
94 event_time,
95 handled: input_device::Handled::No,
96 trace_id: _,
97 } => {
98 self.inspect_status
99 .count_received_event(input_device::InputEvent::from(input_event.clone()));
100 if let Err(e) =
102 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
103 {
104 self.metrics_logger.log_error(
105 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
106 std::format!("update_cursor_renderer failed: {}", e));
107 }
108
109 if let Err(e) = self
111 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
112 .await
113 {
114 self.metrics_logger.log_error(
115 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
116 std::format!("ensure_injector_registered failed: {}", e));
117 }
118
119 if let Err(e) = self
121 .send_event_to_scenic(&mouse_event, &mouse_device_descriptor, event_time)
122 .await
123 {
124 self.metrics_logger.log_error(
125 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
126 std::format!("send_event_to_scenic failed: {}", e));
127 }
128
129 input_event.handled = input_device::Handled::Yes;
131 self.inspect_status.count_handled_event();
132 }
133 _ => {}
134 }
135 vec![input_event]
136 }
137
138 fn set_handler_healthy(self: std::rc::Rc<Self>) {
139 self.inspect_status.health_node.borrow_mut().set_ok();
140 }
141
142 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
143 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
144 }
145}
146
147impl MouseInjectorHandler {
148 pub async fn new(
161 display_size: Size,
162 cursor_message_sender: Sender<CursorMessage>,
163 input_handlers_node: &fuchsia_inspect::Node,
164 metrics_logger: metrics::MetricsLogger,
165 ) -> Result<Rc<Self>, Error> {
166 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
167 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
168
169 Self::new_handler(
170 configuration_proxy,
171 injector_registry_proxy,
172 display_size,
173 cursor_message_sender,
174 input_handlers_node,
175 metrics_logger,
176 )
177 .await
178 }
179
180 pub async fn new_with_config_proxy(
196 configuration_proxy: pointerinjector_config::SetupProxy,
197 display_size: Size,
198 cursor_message_sender: Sender<CursorMessage>,
199 input_handlers_node: &fuchsia_inspect::Node,
200 metrics_logger: metrics::MetricsLogger,
201 ) -> Result<Rc<Self>, Error> {
202 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
203 Self::new_handler(
204 configuration_proxy,
205 injector_registry_proxy,
206 display_size,
207 cursor_message_sender,
208 input_handlers_node,
209 metrics_logger,
210 )
211 .await
212 }
213
214 fn inner(&self) -> Ref<'_, MutableState> {
215 self.mutable_state.borrow()
216 }
217
218 fn inner_mut(&self) -> RefMut<'_, MutableState> {
219 self.mutable_state.borrow_mut()
220 }
221
222 async fn new_handler(
238 configuration_proxy: pointerinjector_config::SetupProxy,
239 injector_registry_proxy: pointerinjector::RegistryProxy,
240 display_size: Size,
241 cursor_message_sender: Sender<CursorMessage>,
242 input_handlers_node: &fuchsia_inspect::Node,
243 metrics_logger: metrics::MetricsLogger,
244 ) -> Result<Rc<Self>, Error> {
245 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
247 let inspect_status = InputHandlerStatus::new(
248 input_handlers_node,
249 "mouse_injector_handler",
250 false,
251 );
252 let handler = Rc::new(Self {
253 mutable_state: RefCell::new(MutableState {
254 viewport: None,
255 injectors: HashMap::new(),
256 current_position: Position {
258 x: display_size.width / 2.0,
259 y: display_size.height / 2.0,
260 },
261 cursor_message_sender,
262 }),
263 context_view_ref,
264 target_view_ref,
265 max_position: Position { x: display_size.width, y: display_size.height },
266 injector_registry_proxy,
267 configuration_proxy,
268 inspect_status,
269 metrics_logger,
270 });
271
272 Ok(handler)
273 }
274
275 async fn ensure_injector_registered(
283 self: &Rc<Self>,
284 mouse_event: &mouse_binding::MouseEvent,
285 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
286 event_time: zx::MonotonicInstant,
287 ) -> Result<(), anyhow::Error> {
288 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
289 return Ok(());
290 }
291
292 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
294 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
295 .context("Failed to duplicate context view ref.")?;
296 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
297 .context("Failed to duplicate target view ref.")?;
298
299 let viewport = self.inner().viewport.clone();
300 let config = pointerinjector::Config {
301 device_id: Some(mouse_descriptor.device_id),
302 device_type: Some(pointerinjector::DeviceType::Mouse),
303 context: Some(pointerinjector::Context::View(context)),
304 target: Some(pointerinjector::Target::View(target)),
305 viewport,
306 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
307 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
308 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
309 buttons: mouse_descriptor.buttons.clone(),
310 ..Default::default()
311 };
312
313 self.injector_registry_proxy
315 .register(config, device_server)
316 .await
317 .context("Failed to register injector.")?;
318 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
319
320 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
322
323 let events_to_send = &[self.create_pointer_sample_event(
325 mouse_event,
326 event_time,
327 pointerinjector::EventPhase::Add,
328 self.inner().current_position,
329 None,
330 )];
331 device_proxy.inject(events_to_send).await.context("Failed to ADD new MouseDevice.")?;
332
333 Ok(())
334 }
335
336 async fn update_cursor_renderer(
347 &self,
348 mouse_event: &mouse_binding::MouseEvent,
349 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
350 ) -> Result<(), anyhow::Error> {
351 let mut new_position = match (mouse_event.location, mouse_descriptor) {
352 (
353 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
354 millimeters,
355 }),
356 _,
357 ) => {
358 self.inner().current_position
359 + self.relative_movement_mm_to_phyical_pixel(millimeters)
360 }
361 (
362 mouse_binding::MouseLocation::Absolute(position),
363 mouse_binding::MouseDeviceDescriptor {
364 absolute_x_range: Some(x_range),
365 absolute_y_range: Some(y_range),
366 ..
367 },
368 ) => self.scale_absolute_position(&position, &x_range, &y_range),
369 (mouse_binding::MouseLocation::Absolute(_), _) => {
370 return Err(anyhow!(
371 "Received an Absolute mouse location without absolute device ranges."
372 ))
373 }
374 };
375 Position::clamp(&mut new_position, Position::zero(), self.max_position);
376 self.inner_mut().current_position = new_position;
377
378 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
379 cursor_message_sender
380 .send(CursorMessage::SetPosition(new_position))
381 .await
382 .context("Failed to send current mouse position to cursor renderer")?;
383
384 Ok(())
385 }
386
387 fn scale_absolute_position(
395 &self,
396 position: &Position,
397 x_range: &Range,
398 y_range: &Range,
399 ) -> Position {
400 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
401 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
402 self.max_position * ((*position - range_min) / (range_max - range_min))
403 }
404
405 async fn send_event_to_scenic(
412 &self,
413 mouse_event: &mouse_binding::MouseEvent,
414 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
415 event_time: zx::MonotonicInstant,
416 ) -> Result<(), anyhow::Error> {
417 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
418 if let Some(injector) = injector {
419 let relative_motion = match mouse_event.location {
420 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
421 millimeters: offset_mm,
422 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
423 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
424 Some([offset.x, offset.y])
425 }
426 _ => None,
427 };
428 let events_to_send = &[self.create_pointer_sample_event(
429 mouse_event,
430 event_time,
431 pointerinjector::EventPhase::Change,
432 self.inner().current_position,
433 relative_motion,
434 )];
435 let _ = injector.inject(events_to_send).await;
436
437 Ok(())
438 } else {
439 Err(anyhow::format_err!(
440 "No injector found for mouse device {}.",
441 mouse_descriptor.device_id
442 ))
443 }
444 }
445
446 fn create_pointer_sample_event(
455 &self,
456 mouse_event: &mouse_binding::MouseEvent,
457 event_time: zx::MonotonicInstant,
458 phase: pointerinjector::EventPhase,
459 current_position: Position,
460 relative_motion: Option<[f32; 2]>,
461 ) -> pointerinjector::Event {
462 let pointer_sample = pointerinjector::PointerSample {
463 pointer_id: Some(0),
464 phase: Some(phase),
465 position_in_viewport: Some([current_position.x, current_position.y]),
466 scroll_v: match mouse_event.wheel_delta_v {
467 Some(mouse_binding::WheelDelta {
468 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
469 ..
470 }) => Some(tick),
471 _ => None,
472 },
473 scroll_h: match mouse_event.wheel_delta_h {
474 Some(mouse_binding::WheelDelta {
475 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
476 ..
477 }) => Some(tick),
478 _ => None,
479 },
480 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
481 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
482 Some(pixel.into())
483 }
484 _ => None,
485 },
486 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
487 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
488 Some(pixel.into())
489 }
490 _ => None,
491 },
492 is_precision_scroll: match mouse_event.phase {
493 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
494 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
495 Some(mouse_binding::PrecisionScroll::No) => Some(false),
496 None => {
497 self.metrics_logger.log_error(
498 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
499 "mouse wheel event does not have value in is_precision_scroll.");
500 None
501 }
502 },
503 _ => None,
504 },
505 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
506 relative_motion,
507 ..Default::default()
508 };
509 pointerinjector::Event {
510 timestamp: Some(event_time.into_nanos()),
511 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
512 trace_flow_id: None,
513 ..Default::default()
514 }
515 }
516
517 pub async fn watch_viewport(self: Rc<Self>) {
519 let configuration_proxy = self.configuration_proxy.clone();
520 let mut viewport_stream = HangingGetStream::new(
521 configuration_proxy,
522 pointerinjector_config::SetupProxy::watch_viewport,
523 );
524 loop {
525 match viewport_stream.next().await {
526 Some(Ok(new_viewport)) => {
527 self.inner_mut().viewport = Some(new_viewport.clone());
529
530 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
532 for injector in injectors {
533 let events = &[pointerinjector::Event {
534 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
535 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
536 trace_flow_id: Some(fuchsia_trace::Id::new().into()),
537 ..Default::default()
538 }];
539 injector.inject(events).await.expect("Failed to inject updated viewport.");
540 }
541 }
542 Some(Err(e)) => {
543 self.metrics_logger.log_error(
544 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
545 std::format!("Error while reading viewport update: {}", e));
546 return;
547 }
548 None => {
549 self.metrics_logger.log_error(
550 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
551 "Viewport update stream terminated unexpectedly");
552 return;
553 }
554 }
555 }
556 }
557
558 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
562 Position {
563 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
564 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
565 }
566 }
567}
568
569#[cfg(test)]
570mod tests {
571 use super::*;
572 use crate::testing_utilities::{
573 assert_handler_ignores_input_event_sequence, create_mouse_event,
574 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
575 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
576 };
577 use assert_matches::assert_matches;
578 use futures::channel::mpsc;
579 use pretty_assertions::assert_eq;
580 use std::collections::HashSet;
581 use std::ops::Add;
582 use test_case::test_case;
583 use {
584 fidl_fuchsia_input_report as fidl_input_report,
585 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
586 };
587
588 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
589 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
590 const COUNTS_PER_MM: u32 = 12;
591
592 const DESCRIPTOR: input_device::InputDeviceDescriptor =
594 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
595 device_id: 1,
596 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
597 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
598 wheel_v_range: Some(fidl_input_report::Axis {
599 range: fidl_input_report::Range { min: -1, max: 1 },
600 unit: fidl_input_report::Unit {
601 type_: fidl_input_report::UnitType::Other,
602 exponent: 0,
603 },
604 }),
605 wheel_h_range: Some(fidl_input_report::Axis {
606 range: fidl_input_report::Range { min: -1, max: 1 },
607 unit: fidl_input_report::Unit {
608 type_: fidl_input_report::UnitType::Other,
609 exponent: 0,
610 },
611 }),
612 buttons: None,
613 counts_per_mm: COUNTS_PER_MM,
614 });
615
616 async fn handle_configuration_request_stream(
618 stream: &mut pointerinjector_config::SetupRequestStream,
619 ) {
620 if let Some(Ok(request)) = stream.next().await {
621 match request {
622 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
623 let context = fuchsia_scenic::ViewRefPair::new()
624 .expect("Failed to create viewrefpair.")
625 .view_ref;
626 let target = fuchsia_scenic::ViewRefPair::new()
627 .expect("Failed to create viewrefpair.")
628 .view_ref;
629 let _ = responder.send(context, target);
630 }
631 _ => {}
632 };
633 }
634 }
635
636 async fn handle_registry_request_stream(
639 mut stream: pointerinjector::RegistryRequestStream,
640 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
641 ) {
642 if let Some(request) = stream.next().await {
643 match request {
644 Ok(pointerinjector::RegistryRequest::Register {
645 config: _,
646 injector,
647 responder,
648 ..
649 }) => {
650 let injector_stream = injector.into_stream();
651 let _ = injector_sender.send(injector_stream);
652 responder.send().expect("failed to respond");
653 }
654 _ => {}
655 };
656 } else {
657 panic!("RegistryRequestStream failed.");
658 }
659 }
660
661 async fn handle_registry_request_stream2(
663 mut stream: pointerinjector::RegistryRequestStream,
664 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
665 ) {
666 let (injector, responder) = match stream.next().await {
667 Some(Ok(pointerinjector::RegistryRequest::Register {
668 config: _,
669 injector,
670 responder,
671 ..
672 })) => (injector, responder),
673 other => panic!("expected register request, but got {:?}", other),
674 };
675 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
676 responder.send().expect("failed to respond");
677 injector_stream
678 .for_each(|request| {
679 futures::future::ready({
680 match request {
681 Ok(pointerinjector::DeviceRequest::Inject {
682 events,
683 responder: device_injector_responder,
684 }) => {
685 let _ = injector_sender.unbounded_send(events);
686 device_injector_responder.send().expect("failed to respond")
687 }
688 Err(e) => panic!("FIDL error {}", e),
689 }
690 })
691 })
692 .await;
693 }
694
695 async fn handle_device_request_stream(
698 injector_stream_receiver: futures::channel::oneshot::Receiver<
699 pointerinjector::DeviceRequestStream,
700 >,
701 expected_events: Vec<pointerinjector::Event>,
702 ) {
703 let mut injector_stream =
704 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
705 for expected_event in expected_events {
706 match injector_stream.next().await {
707 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
708 assert_eq!(events, vec![expected_event]);
709 responder.send().expect("failed to respond");
710 }
711 Some(Err(e)) => panic!("FIDL error {}", e),
712 None => panic!("Expected another event."),
713 }
714 }
715 }
716
717 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
719 pointerinjector::Viewport {
720 extents: Some([[min, min], [max, max]]),
721 viewport_to_context_transform: None,
722 ..Default::default()
723 }
724 }
725
726 #[fuchsia::test]
729 fn receives_viewport_updates() {
730 let mut exec = fasync::TestExecutor::new();
731
732 let (configuration_proxy, mut configuration_request_stream) =
734 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
735 let (injector_registry_proxy, _) =
736 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
737 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
738
739 let inspector = fuchsia_inspect::Inspector::default();
740 let test_node = inspector.root().create_child("test_node");
741
742 let mouse_handler_fut = MouseInjectorHandler::new_handler(
744 configuration_proxy,
745 injector_registry_proxy,
746 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
747 sender,
748 &test_node,
749 metrics::MetricsLogger::default(),
750 );
751 let config_request_stream_fut =
752 handle_configuration_request_stream(&mut configuration_request_stream);
753 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
754 mouse_handler_fut,
755 config_request_stream_fut,
756 ));
757 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
758
759 let (injector_device_proxy, mut injector_device_request_stream) =
761 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
762 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
763
764 {
766 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
768 futures::pin_mut!(watch_viewport_fut);
769 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
770
771 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
773 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
774 responder, ..
775 })) => {
776 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
777 }
778 other => panic!("Received unexpected value: {:?}", other),
779 };
780 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
781
782 exec.run_singlethreaded(async {
784 match injector_device_request_stream.next().await {
785 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
786 assert_eq!(events.len(), 1);
787 assert!(events[0].data.is_some());
788 assert_eq!(
789 events[0].data,
790 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
791 );
792 responder.send().expect("injector stream failed to respond.");
793 }
794 other => panic!("Received unexpected value: {:?}", other),
795 }
796 });
797
798 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
800
801 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
803 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
804 responder, ..
805 })) => {
806 responder
807 .send(&create_viewport(100.0, 200.0))
808 .expect("Failed to send viewport.");
809 }
810 other => panic!("Received unexpected value: {:?}", other),
811 };
812
813 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
815 }
816
817 exec.run_singlethreaded(async {
819 match injector_device_request_stream.next().await {
820 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
821 assert_eq!(events.len(), 1);
822 assert!(events[0].data.is_some());
823 assert_eq!(
824 events[0].data,
825 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
826 );
827 responder.send().expect("injector stream failed to respond.");
828 }
829 other => panic!("Received unexpected value: {:?}", other),
830 }
831 });
832
833 let expected_viewport = create_viewport(100.0, 200.0);
835 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
836 }
837
838 fn wheel_delta_ticks(
839 ticks: i64,
840 physical_pixel: Option<f32>,
841 ) -> Option<mouse_binding::WheelDelta> {
842 Some(mouse_binding::WheelDelta {
843 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
844 physical_pixel,
845 })
846 }
847
848 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
849 Some(mouse_binding::WheelDelta {
850 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
851 physical_pixel,
852 })
853 }
854
855 #[test_case(
858 mouse_binding::MouseLocation::Relative(
859 mouse_binding::RelativeLocation {
860 millimeters: Position { x: 1.0, y: 2.0 }
861 }),
862 Position {
863 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
864 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
865 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
866 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
867 },
868 [
869 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
870 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
871 ]; "Valid move event."
872 )]
873 #[test_case(
874 mouse_binding::MouseLocation::Relative(
875 mouse_binding::RelativeLocation {
876 millimeters: Position {
877 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
878 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
879 }}),
880 Position {
881 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
882 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
883 },
884 [
885 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
886 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
887 ]; "Move event exceeds max bounds."
888 )]
889 #[test_case(
890 mouse_binding::MouseLocation::Relative(
891 mouse_binding::RelativeLocation {
892 millimeters: Position {
893 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
894 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
895 }}),
896 Position { x: 0.0, y: 0.0 },
897 [
898 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
899 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
900 ]; "Move event exceeds min bounds."
901 )]
902 #[fuchsia::test(allow_stalls = false)]
903 async fn move_event(
904 move_location: mouse_binding::MouseLocation,
905 expected_position: Position,
906 expected_relative_motion: [f32; 2],
907 ) {
908 let (configuration_proxy, mut configuration_request_stream) =
910 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
911 let (injector_registry_proxy, injector_registry_request_stream) =
912 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
913 let config_request_stream_fut =
914 handle_configuration_request_stream(&mut configuration_request_stream);
915
916 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
918 let inspector = fuchsia_inspect::Inspector::default();
919 let test_node = inspector.root().create_child("test_node");
920 let mouse_handler_fut = MouseInjectorHandler::new_handler(
921 configuration_proxy,
922 injector_registry_proxy,
923 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
924 sender,
925 &test_node,
926 metrics::MetricsLogger::default(),
927 );
928 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
929 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
930
931 let event_time = zx::MonotonicInstant::get();
932 let input_event = create_mouse_event(
933 move_location,
934 None, None, None, mouse_binding::MousePhase::Move,
938 HashSet::new(),
939 HashSet::new(),
940 event_time,
941 &DESCRIPTOR,
942 );
943
944 let handle_event_fut = mouse_handler.handle_input_event(input_event);
946 let expected_events = vec![
947 create_mouse_pointer_sample_event(
948 pointerinjector::EventPhase::Add,
949 vec![],
950 expected_position,
951 None, None, None, None, event_time,
956 ),
957 create_mouse_pointer_sample_event(
958 pointerinjector::EventPhase::Change,
959 vec![],
960 expected_position,
961 Some(expected_relative_motion),
962 None, None, None, event_time,
966 ),
967 ];
968
969 let (injector_stream_sender, injector_stream_receiver) =
973 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
974 let registry_fut = handle_registry_request_stream(
975 injector_registry_request_stream,
976 injector_stream_sender,
977 );
978 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
979
980 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
983 match receiver.next().await {
984 Some(CursorMessage::SetPosition(position)) => {
985 pretty_assertions::assert_eq!(position, expected_position);
986 }
987 Some(CursorMessage::SetVisibility(_)) => {
988 panic!("Received unexpected cursor visibility update.")
989 }
990 None => panic!("Did not receive cursor update."),
991 }
992
993 assert_matches!(
995 handle_result.as_slice(),
996 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
997 );
998 }
999
1000 #[fuchsia::test(allow_stalls = false)]
1003 async fn move_absolute_event() {
1004 const DEVICE_ID: u32 = 1;
1005
1006 let (configuration_proxy, mut configuration_request_stream) =
1008 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1009 let (injector_registry_proxy, injector_registry_request_stream) =
1010 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1011 let config_request_stream_fut =
1012 handle_configuration_request_stream(&mut configuration_request_stream);
1013
1014 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1016 let inspector = fuchsia_inspect::Inspector::default();
1017 let test_node = inspector.root().create_child("test_node");
1018 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1019 configuration_proxy,
1020 injector_registry_proxy,
1021 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1022 sender,
1023 &test_node,
1024 metrics::MetricsLogger::default(),
1025 );
1026 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1027 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1028
1029 let cursor_location =
1045 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1046 let event_time = zx::MonotonicInstant::get();
1047 let descriptor =
1048 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1049 device_id: DEVICE_ID,
1050 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1051 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1052 wheel_v_range: None,
1053 wheel_h_range: None,
1054 buttons: None,
1055 counts_per_mm: COUNTS_PER_MM,
1056 });
1057 let input_event = create_mouse_event(
1058 cursor_location,
1059 None, None, None, mouse_binding::MousePhase::Move,
1063 HashSet::new(),
1064 HashSet::new(),
1065 event_time,
1066 &descriptor,
1067 );
1068
1069 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1071 let expected_position = Position {
1072 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1073 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1074 };
1075 let expected_events = vec![
1076 create_mouse_pointer_sample_event(
1077 pointerinjector::EventPhase::Add,
1078 vec![],
1079 expected_position,
1080 None, None, None, None, event_time,
1085 ),
1086 create_mouse_pointer_sample_event(
1087 pointerinjector::EventPhase::Change,
1088 vec![],
1089 expected_position,
1090 None, None, None, None, event_time,
1095 ),
1096 ];
1097
1098 let (injector_stream_sender, injector_stream_receiver) =
1102 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1103 let registry_fut = handle_registry_request_stream(
1104 injector_registry_request_stream,
1105 injector_stream_sender,
1106 );
1107 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1108
1109 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1112 match receiver.next().await {
1113 Some(CursorMessage::SetPosition(position)) => {
1114 assert_eq!(position, expected_position);
1115 }
1116 Some(CursorMessage::SetVisibility(_)) => {
1117 panic!("Received unexpected cursor visibility update.")
1118 }
1119 None => panic!("Did not receive cursor update."),
1120 }
1121
1122 assert_matches!(
1124 handle_result.as_slice(),
1125 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1126 );
1127 }
1128
1129 #[test_case(
1131 mouse_binding::MousePhase::Down,
1132 vec![1], vec![1]; "Down event injects button press state."
1133 )]
1134 #[test_case(
1135 mouse_binding::MousePhase::Up,
1136 vec![1], vec![]; "Up event injects button press state."
1137 )]
1138 #[fuchsia::test(allow_stalls = false)]
1139 async fn button_state_event(
1140 phase: mouse_binding::MousePhase,
1141 affected_buttons: Vec<mouse_binding::MouseButton>,
1142 pressed_buttons: Vec<mouse_binding::MouseButton>,
1143 ) {
1144 let (configuration_proxy, mut configuration_request_stream) =
1146 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1147 let (injector_registry_proxy, injector_registry_request_stream) =
1148 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1149 let config_request_stream_fut =
1150 handle_configuration_request_stream(&mut configuration_request_stream);
1151
1152 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1154 let inspector = fuchsia_inspect::Inspector::default();
1155 let test_node = inspector.root().create_child("test_node");
1156 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1157 configuration_proxy,
1158 injector_registry_proxy,
1159 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1160 sender,
1161 &test_node,
1162 metrics::MetricsLogger::default(),
1163 );
1164 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1165 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1166
1167 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1168 let event_time = zx::MonotonicInstant::get();
1169
1170 let input_event = create_mouse_event(
1171 cursor_location,
1172 None, None, None, phase,
1176 HashSet::from_iter(affected_buttons.clone()),
1177 HashSet::from_iter(pressed_buttons.clone()),
1178 event_time,
1179 &DESCRIPTOR,
1180 );
1181
1182 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1184 let expected_position = Position { x: 0.0, y: 0.0 };
1185 let expected_events = vec![
1186 create_mouse_pointer_sample_event(
1187 pointerinjector::EventPhase::Add,
1188 pressed_buttons.clone(),
1189 expected_position,
1190 None, None, None, None, event_time,
1195 ),
1196 create_mouse_pointer_sample_event(
1197 pointerinjector::EventPhase::Change,
1198 pressed_buttons.clone(),
1199 expected_position,
1200 None, None, None, None, event_time,
1205 ),
1206 ];
1207
1208 let (injector_stream_sender, injector_stream_receiver) =
1212 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1213 let registry_fut = handle_registry_request_stream(
1214 injector_registry_request_stream,
1215 injector_stream_sender,
1216 );
1217 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1218
1219 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1222 match receiver.next().await {
1223 Some(CursorMessage::SetPosition(position)) => {
1224 pretty_assertions::assert_eq!(position, expected_position);
1225 }
1226 Some(CursorMessage::SetVisibility(_)) => {
1227 panic!("Received unexpected cursor visibility update.")
1228 }
1229 None => panic!("Did not receive cursor update."),
1230 }
1231
1232 assert_matches!(
1234 handle_result.as_slice(),
1235 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1236 );
1237 }
1238
1239 #[fuchsia::test(allow_stalls = false)]
1241 async fn down_up_event() {
1242 let (configuration_proxy, mut configuration_request_stream) =
1244 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1245 let (injector_registry_proxy, injector_registry_request_stream) =
1246 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1247 let config_request_stream_fut =
1248 handle_configuration_request_stream(&mut configuration_request_stream);
1249
1250 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1254 let inspector = fuchsia_inspect::Inspector::default();
1255 let test_node = inspector.root().create_child("test_node");
1256 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1257 configuration_proxy,
1258 injector_registry_proxy,
1259 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1260 sender,
1261 &test_node,
1262 metrics::MetricsLogger::default(),
1263 );
1264 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1265 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1266
1267 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1268 let event_time1 = zx::MonotonicInstant::get();
1269 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1270
1271 let event1 = create_mouse_event(
1272 cursor_location,
1273 None, None, None, mouse_binding::MousePhase::Down,
1277 HashSet::from_iter(vec![1]),
1278 HashSet::from_iter(vec![1]),
1279 event_time1,
1280 &DESCRIPTOR,
1281 );
1282
1283 let event2 = create_mouse_event(
1284 cursor_location,
1285 None, None, None, mouse_binding::MousePhase::Up,
1289 HashSet::from_iter(vec![1]),
1290 HashSet::new(),
1291 event_time2,
1292 &DESCRIPTOR,
1293 );
1294
1295 let expected_position = Position { x: 0.0, y: 0.0 };
1296
1297 let (injector_stream_sender, injector_stream_receiver) =
1301 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1302 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1304 let registry_fut = handle_registry_request_stream2(
1305 injector_registry_request_stream,
1306 injector_stream_sender,
1307 );
1308
1309 let _registry_task = fasync::Task::local(registry_fut);
1311
1312 mouse_handler.clone().handle_input_event(event1).await;
1313 assert_eq!(
1314 injector_stream_receiver.next().await.map(|events| events.concat()),
1315 Some(vec![
1316 create_mouse_pointer_sample_event(
1317 pointerinjector::EventPhase::Add,
1318 vec![1],
1319 expected_position,
1320 None, None, None, None, event_time1,
1325 ),
1326 create_mouse_pointer_sample_event(
1327 pointerinjector::EventPhase::Change,
1328 vec![1],
1329 expected_position,
1330 None, None, None, None, event_time1,
1335 )
1336 ])
1337 );
1338
1339 mouse_handler.clone().handle_input_event(event2).await;
1341 assert_eq!(
1342 injector_stream_receiver.next().await.map(|events| events.concat()),
1343 Some(vec![create_mouse_pointer_sample_event(
1344 pointerinjector::EventPhase::Change,
1345 vec![],
1346 expected_position,
1347 None, None, None, None, event_time2,
1352 )])
1353 );
1354
1355 match receiver.next().await {
1357 Some(CursorMessage::SetPosition(position)) => {
1358 assert_eq!(position, expected_position);
1359 }
1360 Some(CursorMessage::SetVisibility(_)) => {
1361 panic!("Received unexpected cursor visibility update.")
1362 }
1363 None => panic!("Did not receive cursor update."),
1364 }
1365 }
1366
1367 #[fuchsia::test(allow_stalls = false)]
1377 async fn down_down_up_up_event() {
1378 let (configuration_proxy, mut configuration_request_stream) =
1380 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1381 let (injector_registry_proxy, injector_registry_request_stream) =
1382 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1383 let config_request_stream_fut =
1384 handle_configuration_request_stream(&mut configuration_request_stream);
1385
1386 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1390 let inspector = fuchsia_inspect::Inspector::default();
1391 let test_node = inspector.root().create_child("test_node");
1392 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1393 configuration_proxy,
1394 injector_registry_proxy,
1395 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1396 sender,
1397 &test_node,
1398 metrics::MetricsLogger::default(),
1399 );
1400 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1401 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1402
1403 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1404 let event_time1 = zx::MonotonicInstant::get();
1405 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1406 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1407 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1408
1409 let event1 = create_mouse_event(
1410 cursor_location,
1411 None, None, None, mouse_binding::MousePhase::Down,
1415 HashSet::from_iter(vec![1]),
1416 HashSet::from_iter(vec![1]),
1417 event_time1,
1418 &DESCRIPTOR,
1419 );
1420 let event2 = create_mouse_event(
1421 cursor_location,
1422 None, None, None, mouse_binding::MousePhase::Down,
1426 HashSet::from_iter(vec![2]),
1427 HashSet::from_iter(vec![1, 2]),
1428 event_time2,
1429 &DESCRIPTOR,
1430 );
1431 let event3 = create_mouse_event(
1432 cursor_location,
1433 None, None, None, mouse_binding::MousePhase::Up,
1437 HashSet::from_iter(vec![1]),
1438 HashSet::from_iter(vec![2]),
1439 event_time3,
1440 &DESCRIPTOR,
1441 );
1442 let event4 = create_mouse_event(
1443 cursor_location,
1444 None, None, None, mouse_binding::MousePhase::Up,
1448 HashSet::from_iter(vec![2]),
1449 HashSet::new(),
1450 event_time4,
1451 &DESCRIPTOR,
1452 );
1453
1454 let expected_position = Position { x: 0.0, y: 0.0 };
1455
1456 let (injector_stream_sender, injector_stream_receiver) =
1460 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1461 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1463 let registry_fut = handle_registry_request_stream2(
1464 injector_registry_request_stream,
1465 injector_stream_sender,
1466 );
1467
1468 let _registry_task = fasync::Task::local(registry_fut);
1470 mouse_handler.clone().handle_input_event(event1).await;
1471 assert_eq!(
1472 injector_stream_receiver.next().await.map(|events| events.concat()),
1473 Some(vec![
1474 create_mouse_pointer_sample_event(
1475 pointerinjector::EventPhase::Add,
1476 vec![1],
1477 expected_position,
1478 None, None, None, None, event_time1,
1483 ),
1484 create_mouse_pointer_sample_event(
1485 pointerinjector::EventPhase::Change,
1486 vec![1],
1487 expected_position,
1488 None, None, None, None, event_time1,
1493 )
1494 ])
1495 );
1496
1497 mouse_handler.clone().handle_input_event(event2).await;
1499 let pointer_sample_event2 = injector_stream_receiver
1500 .next()
1501 .await
1502 .map(|events| events.concat())
1503 .expect("Failed to receive pointer sample event.");
1504 let expected_event_time: i64 = event_time2.into_nanos();
1505 assert_eq!(pointer_sample_event2.len(), 1);
1506
1507 match &pointer_sample_event2[0] {
1510 pointerinjector::Event {
1511 timestamp: Some(actual_event_time),
1512 data:
1513 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1514 pointer_id: Some(0),
1515 phase: Some(pointerinjector::EventPhase::Change),
1516 position_in_viewport: Some(actual_position),
1517 scroll_v: None,
1518 scroll_h: None,
1519 pressed_buttons: Some(actual_buttons),
1520 relative_motion: None,
1521 ..
1522 })),
1523 ..
1524 } => {
1525 assert_eq!(actual_event_time, &expected_event_time);
1526 assert_eq!(actual_position[0], expected_position.x);
1527 assert_eq!(actual_position[1], expected_position.y);
1528 assert_eq!(
1529 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1530 HashSet::from_iter(vec![1, 2])
1531 );
1532 }
1533 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1534 }
1535
1536 mouse_handler.clone().handle_input_event(event3).await;
1538 assert_eq!(
1539 injector_stream_receiver.next().await.map(|events| events.concat()),
1540 Some(vec![create_mouse_pointer_sample_event(
1541 pointerinjector::EventPhase::Change,
1542 vec![2],
1543 expected_position,
1544 None, None, None, None, event_time3,
1549 )])
1550 );
1551
1552 mouse_handler.clone().handle_input_event(event4).await;
1554 assert_eq!(
1555 injector_stream_receiver.next().await.map(|events| events.concat()),
1556 Some(vec![create_mouse_pointer_sample_event(
1557 pointerinjector::EventPhase::Change,
1558 vec![],
1559 expected_position,
1560 None, None, None, None, event_time4,
1565 )])
1566 );
1567
1568 match receiver.next().await {
1570 Some(CursorMessage::SetPosition(position)) => {
1571 assert_eq!(position, expected_position);
1572 }
1573 Some(CursorMessage::SetVisibility(_)) => {
1574 panic!("Received unexpected cursor visibility update.")
1575 }
1576 None => panic!("Did not receive cursor update."),
1577 }
1578 }
1579
1580 #[fuchsia::test(allow_stalls = false)]
1582 async fn down_move_up_event() {
1583 let (configuration_proxy, mut configuration_request_stream) =
1585 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1586 let (injector_registry_proxy, injector_registry_request_stream) =
1587 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1588 let config_request_stream_fut =
1589 handle_configuration_request_stream(&mut configuration_request_stream);
1590
1591 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1595 let inspector = fuchsia_inspect::Inspector::default();
1596 let test_node = inspector.root().create_child("test_node");
1597 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1598 configuration_proxy,
1599 injector_registry_proxy,
1600 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1601 sender,
1602 &test_node,
1603 metrics::MetricsLogger::default(),
1604 );
1605 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1606 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1607
1608 let event_time1 = zx::MonotonicInstant::get();
1609 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1610 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1611 let zero_position = Position { x: 0.0, y: 0.0 };
1612 let expected_position = Position {
1613 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1614 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1615 };
1616 let expected_relative_motion = [
1617 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1618 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1619 ];
1620 let event1 = create_mouse_event(
1621 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1622 None, None, None, mouse_binding::MousePhase::Down,
1626 HashSet::from_iter(vec![1]),
1627 HashSet::from_iter(vec![1]),
1628 event_time1,
1629 &DESCRIPTOR,
1630 );
1631 let event2 = create_mouse_event(
1632 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1633 millimeters: Position { x: 10.0, y: 5.0 },
1634 }),
1635 None, None, None, mouse_binding::MousePhase::Move,
1639 HashSet::from_iter(vec![1]),
1640 HashSet::from_iter(vec![1]),
1641 event_time2,
1642 &DESCRIPTOR,
1643 );
1644 let event3 = create_mouse_event(
1645 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1646 millimeters: Position { x: 0.0, y: 0.0 },
1647 }),
1648 None, None, None, mouse_binding::MousePhase::Up,
1652 HashSet::from_iter(vec![1]),
1653 HashSet::from_iter(vec![]),
1654 event_time3,
1655 &DESCRIPTOR,
1656 );
1657
1658 let (injector_stream_sender, injector_stream_receiver) =
1662 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1663 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1665 let registry_fut = handle_registry_request_stream2(
1666 injector_registry_request_stream,
1667 injector_stream_sender,
1668 );
1669
1670 let _registry_task = fasync::Task::local(registry_fut);
1672 mouse_handler.clone().handle_input_event(event1).await;
1673 assert_eq!(
1674 injector_stream_receiver.next().await.map(|events| events.concat()),
1675 Some(vec![
1676 create_mouse_pointer_sample_event(
1677 pointerinjector::EventPhase::Add,
1678 vec![1],
1679 zero_position,
1680 None, None, None, None, event_time1,
1685 ),
1686 create_mouse_pointer_sample_event(
1687 pointerinjector::EventPhase::Change,
1688 vec![1],
1689 zero_position,
1690 None, None, None, None, event_time1,
1695 )
1696 ])
1697 );
1698
1699 match receiver.next().await {
1701 Some(CursorMessage::SetPosition(position)) => {
1702 assert_eq!(position, zero_position);
1703 }
1704 Some(CursorMessage::SetVisibility(_)) => {
1705 panic!("Received unexpected cursor visibility update.")
1706 }
1707 None => panic!("Did not receive cursor update."),
1708 }
1709
1710 mouse_handler.clone().handle_input_event(event2).await;
1712 assert_eq!(
1713 injector_stream_receiver.next().await.map(|events| events.concat()),
1714 Some(vec![create_mouse_pointer_sample_event(
1715 pointerinjector::EventPhase::Change,
1716 vec![1],
1717 expected_position,
1718 Some(expected_relative_motion),
1719 None, None, None, event_time2,
1723 )])
1724 );
1725
1726 match receiver.next().await {
1728 Some(CursorMessage::SetPosition(position)) => {
1729 assert_eq!(position, expected_position);
1730 }
1731 Some(CursorMessage::SetVisibility(_)) => {
1732 panic!("Received unexpected cursor visibility update.")
1733 }
1734 None => panic!("Did not receive cursor update."),
1735 }
1736
1737 mouse_handler.clone().handle_input_event(event3).await;
1739 assert_eq!(
1740 injector_stream_receiver.next().await.map(|events| events.concat()),
1741 Some(vec![create_mouse_pointer_sample_event(
1742 pointerinjector::EventPhase::Change,
1743 vec![],
1744 expected_position,
1745 None, None, None, None, event_time3,
1750 )])
1751 );
1752
1753 match receiver.next().await {
1755 Some(CursorMessage::SetPosition(position)) => {
1756 assert_eq!(position, expected_position);
1757 }
1758 Some(CursorMessage::SetVisibility(_)) => {
1759 panic!("Received unexpected cursor visibility update.")
1760 }
1761 None => panic!("Did not receive cursor update."),
1762 }
1763 }
1764
1765 #[fuchsia::test(allow_stalls = false)]
1767 async fn handler_ignores_handled_events() {
1768 let (configuration_proxy, mut configuration_request_stream) =
1770 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1771 let (injector_registry_proxy, injector_registry_request_stream) =
1772 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1773 let config_request_stream_fut =
1774 handle_configuration_request_stream(&mut configuration_request_stream);
1775
1776 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1778 let inspector = fuchsia_inspect::Inspector::default();
1779 let test_node = inspector.root().create_child("test_node");
1780 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1781 configuration_proxy,
1782 injector_registry_proxy,
1783 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1784 sender,
1785 &test_node,
1786 metrics::MetricsLogger::default(),
1787 );
1788 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1789 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1790
1791 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1792 let cursor_location =
1793 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1794 millimeters: Position {
1795 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1796 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1797 },
1798 });
1799 let event_time = zx::MonotonicInstant::get();
1800 let input_events = vec![create_mouse_event_with_handled(
1801 cursor_location,
1802 None, None, None, mouse_binding::MousePhase::Move,
1806 HashSet::new(),
1807 HashSet::new(),
1808 event_time,
1809 &DESCRIPTOR,
1810 input_device::Handled::Yes,
1811 )];
1812
1813 assert_handler_ignores_input_event_sequence(
1814 mouse_handler,
1815 input_events,
1816 injector_registry_request_stream,
1817 )
1818 .await;
1819
1820 assert!(receiver.next().await.is_none());
1822 }
1823
1824 fn zero_relative_location() -> mouse_binding::MouseLocation {
1825 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1826 millimeters: Position { x: 0.0, y: 0.0 },
1827 })
1828 }
1829
1830 #[test_case(
1831 create_mouse_event(
1832 zero_relative_location(),
1833 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1837 HashSet::new(),
1838 HashSet::new(),
1839 zx::MonotonicInstant::ZERO,
1840 &DESCRIPTOR,
1841 ),
1842 create_mouse_pointer_sample_event(
1843 pointerinjector::EventPhase::Change,
1844 vec![],
1845 Position { x: 50.0, y: 50.0 },
1846 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1851 ); "v tick scroll"
1852 )]
1853 #[test_case(
1854 create_mouse_event(
1855 zero_relative_location(),
1856 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1860 HashSet::new(),
1861 HashSet::new(),
1862 zx::MonotonicInstant::ZERO,
1863 &DESCRIPTOR,
1864 ),
1865 create_mouse_pointer_sample_event(
1866 pointerinjector::EventPhase::Change,
1867 vec![],
1868 Position { x: 50.0, y: 50.0 },
1869 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1874 ); "h tick scroll"
1875 )]
1876 #[test_case(
1877 create_mouse_event(
1878 zero_relative_location(),
1879 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1883 HashSet::new(),
1884 HashSet::new(),
1885 zx::MonotonicInstant::ZERO,
1886 &DESCRIPTOR,
1887 ),
1888 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1889 pointerinjector::EventPhase::Change,
1890 vec![],
1891 Position { x: 50.0, y: 50.0 },
1892 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1899 ); "v tick scroll with physical pixel"
1900 )]
1901 #[test_case(
1902 create_mouse_event(
1903 zero_relative_location(),
1904 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1908 HashSet::new(),
1909 HashSet::new(),
1910 zx::MonotonicInstant::ZERO,
1911 &DESCRIPTOR,
1912 ),
1913 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1914 pointerinjector::EventPhase::Change,
1915 vec![],
1916 Position { x: 50.0, y: 50.0 },
1917 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1924 ); "h tick scroll with physical pixel"
1925 )]
1926 #[test_case(
1927 create_mouse_event(
1928 zero_relative_location(),
1929 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1933 HashSet::new(),
1934 HashSet::new(),
1935 zx::MonotonicInstant::ZERO,
1936 &DESCRIPTOR,
1937 ),
1938 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1939 pointerinjector::EventPhase::Change,
1940 vec![],
1941 Position { x: 50.0, y: 50.0 },
1942 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1949 ); "v mm scroll with physical pixel"
1950 )]
1951 #[test_case(
1952 create_mouse_event(
1953 zero_relative_location(),
1954 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1958 HashSet::new(),
1959 HashSet::new(),
1960 zx::MonotonicInstant::ZERO,
1961 &DESCRIPTOR,
1962 ),
1963 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1964 pointerinjector::EventPhase::Change,
1965 vec![],
1966 Position { x: 50.0, y: 50.0 },
1967 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1974 ); "h mm scroll with physical pixel"
1975 )]
1976 #[fuchsia::test(allow_stalls = false)]
1978 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1979 let (configuration_proxy, mut configuration_request_stream) =
1981 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1982 let (injector_registry_proxy, injector_registry_request_stream) =
1983 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1984 let config_request_stream_fut =
1985 handle_configuration_request_stream(&mut configuration_request_stream);
1986
1987 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1989 let inspector = fuchsia_inspect::Inspector::default();
1990 let test_node = inspector.root().create_child("test_node");
1991 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1992 configuration_proxy,
1993 injector_registry_proxy,
1994 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1995 sender,
1996 &test_node,
1997 metrics::MetricsLogger::default(),
1998 );
1999 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2000 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2001
2002 let (injector_stream_sender, injector_stream_receiver) =
2006 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2007 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2009 let registry_fut = handle_registry_request_stream2(
2010 injector_registry_request_stream,
2011 injector_stream_sender,
2012 );
2013
2014 let event_time = zx::MonotonicInstant::get();
2015
2016 let event = input_device::InputEvent { event_time, ..event };
2017
2018 let want_event =
2019 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2020
2021 let _registry_task = fasync::Task::local(registry_fut);
2023
2024 mouse_handler.clone().handle_input_event(event).await;
2025 let got_events =
2026 injector_stream_receiver.next().await.map(|events| events.concat()).unwrap();
2027 pretty_assertions::assert_eq!(got_events.len(), 2);
2028 assert_matches!(
2029 got_events[0],
2030 pointerinjector::Event {
2031 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2032 phase: Some(pointerinjector::EventPhase::Add),
2033 ..
2034 })),
2035 ..
2036 }
2037 );
2038
2039 pretty_assertions::assert_eq!(got_events[1], want_event);
2040 }
2041
2042 #[fuchsia::test(allow_stalls = false)]
2044 async fn down_scroll_up_scroll() {
2045 let (configuration_proxy, mut configuration_request_stream) =
2047 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2048 let (injector_registry_proxy, injector_registry_request_stream) =
2049 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2050 let config_request_stream_fut =
2051 handle_configuration_request_stream(&mut configuration_request_stream);
2052
2053 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2055 let inspector = fuchsia_inspect::Inspector::default();
2056 let test_node = inspector.root().create_child("test_node");
2057 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2058 configuration_proxy,
2059 injector_registry_proxy,
2060 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2061 sender,
2062 &test_node,
2063 metrics::MetricsLogger::default(),
2064 );
2065 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2066 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2067
2068 let (injector_stream_sender, injector_stream_receiver) =
2072 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2073 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2075 let registry_fut = handle_registry_request_stream2(
2076 injector_registry_request_stream,
2077 injector_stream_sender,
2078 );
2079
2080 let event_time1 = zx::MonotonicInstant::get();
2081 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2082 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2083 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2084
2085 let _registry_task = fasync::Task::local(registry_fut);
2087
2088 let zero_location =
2089 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2090 millimeters: Position { x: 0.0, y: 0.0 },
2091 });
2092 let expected_position = Position { x: 50.0, y: 50.0 };
2093
2094 let down_event = create_mouse_event(
2095 zero_location,
2096 None, None, None, mouse_binding::MousePhase::Down,
2100 HashSet::from_iter(vec![1]),
2101 HashSet::from_iter(vec![1]),
2102 event_time1,
2103 &DESCRIPTOR,
2104 );
2105
2106 let wheel_event = create_mouse_event(
2107 zero_location,
2108 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2112 HashSet::from_iter(vec![1]),
2113 HashSet::from_iter(vec![1]),
2114 event_time2,
2115 &DESCRIPTOR,
2116 );
2117
2118 let up_event = create_mouse_event(
2119 zero_location,
2120 None,
2121 None,
2122 None, mouse_binding::MousePhase::Up,
2124 HashSet::from_iter(vec![1]),
2125 HashSet::new(),
2126 event_time3,
2127 &DESCRIPTOR,
2128 );
2129
2130 let continue_wheel_event = create_mouse_event(
2131 zero_location,
2132 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2136 HashSet::new(),
2137 HashSet::new(),
2138 event_time4,
2139 &DESCRIPTOR,
2140 );
2141
2142 mouse_handler.clone().handle_input_event(down_event).await;
2144 assert_eq!(
2145 injector_stream_receiver.next().await.map(|events| events.concat()),
2146 Some(vec![
2147 create_mouse_pointer_sample_event(
2148 pointerinjector::EventPhase::Add,
2149 vec![1],
2150 expected_position,
2151 None, None, None, None, event_time1,
2156 ),
2157 create_mouse_pointer_sample_event(
2158 pointerinjector::EventPhase::Change,
2159 vec![1],
2160 expected_position,
2161 None, None, None, None, event_time1,
2166 ),
2167 ])
2168 );
2169
2170 mouse_handler.clone().handle_input_event(wheel_event).await;
2172 assert_eq!(
2173 injector_stream_receiver.next().await.map(|events| events.concat()),
2174 Some(vec![create_mouse_pointer_sample_event(
2175 pointerinjector::EventPhase::Change,
2176 vec![1],
2177 expected_position,
2178 None, Some(1), None, Some(false), event_time2,
2183 )])
2184 );
2185
2186 mouse_handler.clone().handle_input_event(up_event).await;
2188 assert_eq!(
2189 injector_stream_receiver.next().await.map(|events| events.concat()),
2190 Some(vec![create_mouse_pointer_sample_event(
2191 pointerinjector::EventPhase::Change,
2192 vec![],
2193 expected_position,
2194 None, None, None, None, event_time3,
2199 )])
2200 );
2201
2202 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2204 assert_eq!(
2205 injector_stream_receiver.next().await.map(|events| events.concat()),
2206 Some(vec![create_mouse_pointer_sample_event(
2207 pointerinjector::EventPhase::Change,
2208 vec![],
2209 expected_position,
2210 None, Some(1), None, Some(false), event_time4,
2215 )])
2216 );
2217 }
2218
2219 #[fuchsia::test(allow_stalls = false)]
2220 async fn mouse_injector_handler_initialized_with_inspect_node() {
2221 let (configuration_proxy, mut configuration_request_stream) =
2222 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2223 let config_request_stream_fut =
2224 handle_configuration_request_stream(&mut configuration_request_stream);
2225 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2226 let inspector = fuchsia_inspect::Inspector::default();
2227 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2228 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2229 configuration_proxy,
2230 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2231 sender,
2232 &fake_handlers_node,
2233 metrics::MetricsLogger::default(),
2234 );
2235 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2236 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2237
2238 diagnostics_assertions::assert_data_tree!(inspector, root: {
2239 input_handlers_node: {
2240 mouse_injector_handler: {
2241 events_received_count: 0u64,
2242 events_handled_count: 0u64,
2243 last_received_timestamp_ns: 0u64,
2244 "fuchsia.inspect.Health": {
2245 status: "STARTING_UP",
2246 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2249 },
2250 }
2251 }
2252 });
2253 }
2254
2255 #[fuchsia::test(allow_stalls = false)]
2256 async fn mouse_injector_handler_inspect_counts_events() {
2257 let (configuration_proxy, mut configuration_request_stream) =
2259 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2260 let (injector_registry_proxy, injector_registry_request_stream) =
2261 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2262 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2263
2264 let inspector = fuchsia_inspect::Inspector::default();
2265 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2266
2267 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2269 configuration_proxy,
2270 injector_registry_proxy,
2271 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2272 sender,
2273 &fake_handlers_node,
2274 metrics::MetricsLogger::default(),
2275 );
2276 let config_request_stream_fut =
2277 handle_configuration_request_stream(&mut configuration_request_stream);
2278
2279 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2280 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2281
2282 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2283 let event_time1 = zx::MonotonicInstant::get();
2284 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2285 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2286
2287 let input_events = vec![
2288 create_mouse_event(
2289 cursor_location,
2290 None, None, None, mouse_binding::MousePhase::Down,
2294 HashSet::from_iter(vec![1]),
2295 HashSet::from_iter(vec![1]),
2296 event_time1,
2297 &DESCRIPTOR,
2298 ),
2299 create_mouse_event(
2300 cursor_location,
2301 None, None, None, mouse_binding::MousePhase::Up,
2305 HashSet::from_iter(vec![1]),
2306 HashSet::new(),
2307 event_time2,
2308 &DESCRIPTOR,
2309 ),
2310 create_mouse_event_with_handled(
2311 cursor_location,
2312 None, None, None, mouse_binding::MousePhase::Down,
2316 HashSet::from_iter(vec![1]),
2317 HashSet::from_iter(vec![1]),
2318 event_time3,
2319 &DESCRIPTOR,
2320 input_device::Handled::Yes,
2321 ),
2322 ];
2323
2324 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2328 let registry_fut = handle_registry_request_stream2(
2329 injector_registry_request_stream,
2330 injector_stream_sender,
2331 );
2332
2333 let _registry_task = fasync::Task::local(registry_fut);
2335 for input_event in input_events {
2336 mouse_handler.clone().handle_input_event(input_event).await;
2337 }
2338
2339 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2340
2341 diagnostics_assertions::assert_data_tree!(inspector, root: {
2342 input_handlers_node: {
2343 mouse_injector_handler: {
2344 events_received_count: 2u64,
2345 events_handled_count: 2u64,
2346 last_received_timestamp_ns: last_received_event_time,
2347 "fuchsia.inspect.Health": {
2348 status: "STARTING_UP",
2349 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2352 },
2353 }
2354 }
2355 });
2356 }
2357}