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 fuchsia_trace::duration!(c"input", c"mouse_injector_hander");
99 let trace_id = match trace_id {
100 Some(id) => {
101 fuchsia_trace::flow_end!(c"input", c"event_in_input_pipeline", id.into());
102 id
103 }
104 None => fuchsia_trace::Id::random(),
105 };
106
107 self.inspect_status
108 .count_received_event(input_device::InputEvent::from(input_event.clone()));
109 if let Err(e) =
111 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
112 {
113 self.metrics_logger.log_error(
114 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
115 std::format!("update_cursor_renderer failed: {}", e));
116 }
117
118 if let Err(e) = self
120 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
121 .await
122 {
123 self.metrics_logger.log_error(
124 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
125 std::format!("ensure_injector_registered failed: {}", e));
126 }
127
128 if let Err(e) = self
130 .send_event_to_scenic(
131 &mouse_event,
132 &mouse_device_descriptor,
133 event_time,
134 trace_id.into(),
135 )
136 .await
137 {
138 self.metrics_logger.log_error(
139 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
140 std::format!("send_event_to_scenic failed: {}", e));
141 }
142
143 input_event.handled = input_device::Handled::Yes;
145 self.inspect_status.count_handled_event();
146 }
147 _ => {}
148 }
149 vec![input_event]
150 }
151
152 fn set_handler_healthy(self: std::rc::Rc<Self>) {
153 self.inspect_status.health_node.borrow_mut().set_ok();
154 }
155
156 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
157 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
158 }
159}
160
161impl MouseInjectorHandler {
162 pub async fn new(
175 display_size: Size,
176 cursor_message_sender: Sender<CursorMessage>,
177 input_handlers_node: &fuchsia_inspect::Node,
178 metrics_logger: metrics::MetricsLogger,
179 ) -> Result<Rc<Self>, Error> {
180 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
181 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
182
183 Self::new_handler(
184 configuration_proxy,
185 injector_registry_proxy,
186 display_size,
187 cursor_message_sender,
188 input_handlers_node,
189 metrics_logger,
190 )
191 .await
192 }
193
194 pub async fn new_with_config_proxy(
210 configuration_proxy: pointerinjector_config::SetupProxy,
211 display_size: Size,
212 cursor_message_sender: Sender<CursorMessage>,
213 input_handlers_node: &fuchsia_inspect::Node,
214 metrics_logger: metrics::MetricsLogger,
215 ) -> Result<Rc<Self>, Error> {
216 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
217 Self::new_handler(
218 configuration_proxy,
219 injector_registry_proxy,
220 display_size,
221 cursor_message_sender,
222 input_handlers_node,
223 metrics_logger,
224 )
225 .await
226 }
227
228 fn inner(&self) -> Ref<'_, MutableState> {
229 self.mutable_state.borrow()
230 }
231
232 fn inner_mut(&self) -> RefMut<'_, MutableState> {
233 self.mutable_state.borrow_mut()
234 }
235
236 async fn new_handler(
252 configuration_proxy: pointerinjector_config::SetupProxy,
253 injector_registry_proxy: pointerinjector::RegistryProxy,
254 display_size: Size,
255 cursor_message_sender: Sender<CursorMessage>,
256 input_handlers_node: &fuchsia_inspect::Node,
257 metrics_logger: metrics::MetricsLogger,
258 ) -> Result<Rc<Self>, Error> {
259 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
261 let inspect_status = InputHandlerStatus::new(
262 input_handlers_node,
263 "mouse_injector_handler",
264 false,
265 );
266 let handler = Rc::new(Self {
267 mutable_state: RefCell::new(MutableState {
268 viewport: None,
269 injectors: HashMap::new(),
270 current_position: Position {
272 x: display_size.width / 2.0,
273 y: display_size.height / 2.0,
274 },
275 cursor_message_sender,
276 }),
277 context_view_ref,
278 target_view_ref,
279 max_position: Position { x: display_size.width, y: display_size.height },
280 injector_registry_proxy,
281 configuration_proxy,
282 inspect_status,
283 metrics_logger,
284 });
285
286 Ok(handler)
287 }
288
289 async fn ensure_injector_registered(
297 self: &Rc<Self>,
298 mouse_event: &mouse_binding::MouseEvent,
299 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
300 event_time: zx::MonotonicInstant,
301 ) -> Result<(), anyhow::Error> {
302 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
303 return Ok(());
304 }
305
306 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
308 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
309 .context("Failed to duplicate context view ref.")?;
310 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
311 .context("Failed to duplicate target view ref.")?;
312
313 let viewport = self.inner().viewport.clone();
314 let config = pointerinjector::Config {
315 device_id: Some(mouse_descriptor.device_id),
316 device_type: Some(pointerinjector::DeviceType::Mouse),
317 context: Some(pointerinjector::Context::View(context)),
318 target: Some(pointerinjector::Target::View(target)),
319 viewport,
320 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
321 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
322 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
323 buttons: mouse_descriptor.buttons.clone(),
324 ..Default::default()
325 };
326
327 self.injector_registry_proxy
329 .register(config, device_server)
330 .await
331 .context("Failed to register injector.")?;
332 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
333
334 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
336
337 let events_to_send = &[self.create_pointer_sample_event(
339 mouse_event,
340 event_time,
341 pointerinjector::EventPhase::Add,
342 self.inner().current_position,
343 None,
344 None,
345 )];
346 device_proxy.inject(events_to_send).await.context("Failed to ADD new MouseDevice.")?;
347
348 Ok(())
349 }
350
351 async fn update_cursor_renderer(
362 &self,
363 mouse_event: &mouse_binding::MouseEvent,
364 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
365 ) -> Result<(), anyhow::Error> {
366 let mut new_position = match (mouse_event.location, mouse_descriptor) {
367 (
368 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
369 millimeters,
370 }),
371 _,
372 ) => {
373 self.inner().current_position
374 + self.relative_movement_mm_to_phyical_pixel(millimeters)
375 }
376 (
377 mouse_binding::MouseLocation::Absolute(position),
378 mouse_binding::MouseDeviceDescriptor {
379 absolute_x_range: Some(x_range),
380 absolute_y_range: Some(y_range),
381 ..
382 },
383 ) => self.scale_absolute_position(&position, &x_range, &y_range),
384 (mouse_binding::MouseLocation::Absolute(_), _) => {
385 return Err(anyhow!(
386 "Received an Absolute mouse location without absolute device ranges."
387 ))
388 }
389 };
390 Position::clamp(&mut new_position, Position::zero(), self.max_position);
391 self.inner_mut().current_position = new_position;
392
393 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
394 cursor_message_sender
395 .send(CursorMessage::SetPosition(new_position))
396 .await
397 .context("Failed to send current mouse position to cursor renderer")?;
398
399 Ok(())
400 }
401
402 fn scale_absolute_position(
410 &self,
411 position: &Position,
412 x_range: &Range,
413 y_range: &Range,
414 ) -> Position {
415 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
416 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
417 self.max_position * ((*position - range_min) / (range_max - range_min))
418 }
419
420 async fn send_event_to_scenic(
427 &self,
428 mouse_event: &mouse_binding::MouseEvent,
429 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
430 event_time: zx::MonotonicInstant,
431 tracing_id: u64,
432 ) -> Result<(), anyhow::Error> {
433 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
434 if let Some(injector) = injector {
435 let relative_motion = match mouse_event.location {
436 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
437 millimeters: offset_mm,
438 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
439 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
440 Some([offset.x, offset.y])
441 }
442 _ => None,
443 };
444 let events_to_send = &[self.create_pointer_sample_event(
445 mouse_event,
446 event_time,
447 pointerinjector::EventPhase::Change,
448 self.inner().current_position,
449 relative_motion,
450 Some(tracing_id),
451 )];
452
453 fuchsia_trace::flow_begin!(c"input", c"dispatch_event_to_scenic", tracing_id.into());
454
455 let _ = injector.inject(events_to_send).await;
456
457 Ok(())
458 } else {
459 Err(anyhow::format_err!(
460 "No injector found for mouse device {}.",
461 mouse_descriptor.device_id
462 ))
463 }
464 }
465
466 fn create_pointer_sample_event(
475 &self,
476 mouse_event: &mouse_binding::MouseEvent,
477 event_time: zx::MonotonicInstant,
478 phase: pointerinjector::EventPhase,
479 current_position: Position,
480 relative_motion: Option<[f32; 2]>,
481 trace_id: Option<u64>,
482 ) -> pointerinjector::Event {
483 let pointer_sample = pointerinjector::PointerSample {
484 pointer_id: Some(0),
485 phase: Some(phase),
486 position_in_viewport: Some([current_position.x, current_position.y]),
487 scroll_v: match mouse_event.wheel_delta_v {
488 Some(mouse_binding::WheelDelta {
489 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
490 ..
491 }) => Some(tick),
492 _ => None,
493 },
494 scroll_h: match mouse_event.wheel_delta_h {
495 Some(mouse_binding::WheelDelta {
496 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
497 ..
498 }) => Some(tick),
499 _ => None,
500 },
501 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
502 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
503 Some(pixel.into())
504 }
505 _ => None,
506 },
507 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
508 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
509 Some(pixel.into())
510 }
511 _ => None,
512 },
513 is_precision_scroll: match mouse_event.phase {
514 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
515 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
516 Some(mouse_binding::PrecisionScroll::No) => Some(false),
517 None => {
518 self.metrics_logger.log_error(
519 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
520 "mouse wheel event does not have value in is_precision_scroll.");
521 None
522 }
523 },
524 _ => None,
525 },
526 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
527 relative_motion,
528 ..Default::default()
529 };
530 pointerinjector::Event {
531 timestamp: Some(event_time.into_nanos()),
532 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
533 trace_flow_id: trace_id,
534 ..Default::default()
535 }
536 }
537
538 pub async fn watch_viewport(self: Rc<Self>) {
540 let configuration_proxy = self.configuration_proxy.clone();
541 let mut viewport_stream = HangingGetStream::new(
542 configuration_proxy,
543 pointerinjector_config::SetupProxy::watch_viewport,
544 );
545 loop {
546 match viewport_stream.next().await {
547 Some(Ok(new_viewport)) => {
548 self.inner_mut().viewport = Some(new_viewport.clone());
550
551 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
553 for injector in injectors {
554 let events = &[pointerinjector::Event {
555 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
556 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
557 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
558 ..Default::default()
559 }];
560 injector.inject(events).await.expect("Failed to inject updated viewport.");
561 }
562 }
563 Some(Err(e)) => {
564 self.metrics_logger.log_error(
565 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
566 std::format!("Error while reading viewport update: {}", e));
567 return;
568 }
569 None => {
570 self.metrics_logger.log_error(
571 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
572 "Viewport update stream terminated unexpectedly");
573 return;
574 }
575 }
576 }
577 }
578
579 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
583 Position {
584 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
585 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
586 }
587 }
588}
589
590#[cfg(test)]
591mod tests {
592 use super::*;
593 use crate::testing_utilities::{
594 assert_handler_ignores_input_event_sequence, create_mouse_event,
595 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
596 create_mouse_pointer_sample_event_phase_add,
597 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
598 };
599 use assert_matches::assert_matches;
600 use futures::channel::mpsc;
601 use pretty_assertions::assert_eq;
602 use std::collections::HashSet;
603 use std::ops::Add;
604 use test_case::test_case;
605 use {
606 fidl_fuchsia_input_report as fidl_input_report,
607 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
608 };
609
610 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
611 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
612 const COUNTS_PER_MM: u32 = 12;
613
614 const DESCRIPTOR: input_device::InputDeviceDescriptor =
616 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
617 device_id: 1,
618 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
619 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
620 wheel_v_range: Some(fidl_input_report::Axis {
621 range: fidl_input_report::Range { min: -1, max: 1 },
622 unit: fidl_input_report::Unit {
623 type_: fidl_input_report::UnitType::Other,
624 exponent: 0,
625 },
626 }),
627 wheel_h_range: Some(fidl_input_report::Axis {
628 range: fidl_input_report::Range { min: -1, max: 1 },
629 unit: fidl_input_report::Unit {
630 type_: fidl_input_report::UnitType::Other,
631 exponent: 0,
632 },
633 }),
634 buttons: None,
635 counts_per_mm: COUNTS_PER_MM,
636 });
637
638 async fn handle_configuration_request_stream(
640 stream: &mut pointerinjector_config::SetupRequestStream,
641 ) {
642 if let Some(Ok(request)) = stream.next().await {
643 match request {
644 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
645 let context = fuchsia_scenic::ViewRefPair::new()
646 .expect("Failed to create viewrefpair.")
647 .view_ref;
648 let target = fuchsia_scenic::ViewRefPair::new()
649 .expect("Failed to create viewrefpair.")
650 .view_ref;
651 let _ = responder.send(context, target);
652 }
653 _ => {}
654 };
655 }
656 }
657
658 async fn handle_registry_request_stream(
661 mut stream: pointerinjector::RegistryRequestStream,
662 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
663 ) {
664 if let Some(request) = stream.next().await {
665 match request {
666 Ok(pointerinjector::RegistryRequest::Register {
667 config: _,
668 injector,
669 responder,
670 ..
671 }) => {
672 let injector_stream = injector.into_stream();
673 let _ = injector_sender.send(injector_stream);
674 responder.send().expect("failed to respond");
675 }
676 _ => {}
677 };
678 } else {
679 panic!("RegistryRequestStream failed.");
680 }
681 }
682
683 async fn handle_registry_request_stream2(
685 mut stream: pointerinjector::RegistryRequestStream,
686 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
687 ) {
688 let (injector, responder) = match stream.next().await {
689 Some(Ok(pointerinjector::RegistryRequest::Register {
690 config: _,
691 injector,
692 responder,
693 ..
694 })) => (injector, responder),
695 other => panic!("expected register request, but got {:?}", other),
696 };
697 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
698 responder.send().expect("failed to respond");
699 injector_stream
700 .for_each(|request| {
701 futures::future::ready({
702 match request {
703 Ok(pointerinjector::DeviceRequest::Inject {
704 events,
705 responder: device_injector_responder,
706 }) => {
707 let _ = injector_sender.unbounded_send(events);
708 device_injector_responder.send().expect("failed to respond")
709 }
710 Err(e) => panic!("FIDL error {}", e),
711 }
712 })
713 })
714 .await;
715 }
716
717 async fn handle_device_request_stream(
720 injector_stream_receiver: futures::channel::oneshot::Receiver<
721 pointerinjector::DeviceRequestStream,
722 >,
723 expected_events: Vec<pointerinjector::Event>,
724 ) {
725 let mut injector_stream =
726 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
727 for expected_event in expected_events {
728 match injector_stream.next().await {
729 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
730 assert_eq!(events, vec![expected_event]);
731 responder.send().expect("failed to respond");
732 }
733 Some(Err(e)) => panic!("FIDL error {}", e),
734 None => panic!("Expected another event."),
735 }
736 }
737 }
738
739 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
741 pointerinjector::Viewport {
742 extents: Some([[min, min], [max, max]]),
743 viewport_to_context_transform: None,
744 ..Default::default()
745 }
746 }
747
748 #[fuchsia::test]
751 fn receives_viewport_updates() {
752 let mut exec = fasync::TestExecutor::new();
753
754 let (configuration_proxy, mut configuration_request_stream) =
756 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
757 let (injector_registry_proxy, _) =
758 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
759 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
760
761 let inspector = fuchsia_inspect::Inspector::default();
762 let test_node = inspector.root().create_child("test_node");
763
764 let mouse_handler_fut = MouseInjectorHandler::new_handler(
766 configuration_proxy,
767 injector_registry_proxy,
768 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
769 sender,
770 &test_node,
771 metrics::MetricsLogger::default(),
772 );
773 let config_request_stream_fut =
774 handle_configuration_request_stream(&mut configuration_request_stream);
775 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
776 mouse_handler_fut,
777 config_request_stream_fut,
778 ));
779 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
780
781 let (injector_device_proxy, mut injector_device_request_stream) =
783 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
784 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
785
786 {
788 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
790 futures::pin_mut!(watch_viewport_fut);
791 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
792
793 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
795 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
796 responder, ..
797 })) => {
798 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
799 }
800 other => panic!("Received unexpected value: {:?}", other),
801 };
802 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
803
804 exec.run_singlethreaded(async {
806 match injector_device_request_stream.next().await {
807 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
808 assert_eq!(events.len(), 1);
809 assert!(events[0].data.is_some());
810 assert_eq!(
811 events[0].data,
812 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
813 );
814 responder.send().expect("injector stream failed to respond.");
815 }
816 other => panic!("Received unexpected value: {:?}", other),
817 }
818 });
819
820 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
822
823 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
825 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
826 responder, ..
827 })) => {
828 responder
829 .send(&create_viewport(100.0, 200.0))
830 .expect("Failed to send viewport.");
831 }
832 other => panic!("Received unexpected value: {:?}", other),
833 };
834
835 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
837 }
838
839 exec.run_singlethreaded(async {
841 match injector_device_request_stream.next().await {
842 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
843 assert_eq!(events.len(), 1);
844 assert!(events[0].data.is_some());
845 assert_eq!(
846 events[0].data,
847 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
848 );
849 responder.send().expect("injector stream failed to respond.");
850 }
851 other => panic!("Received unexpected value: {:?}", other),
852 }
853 });
854
855 let expected_viewport = create_viewport(100.0, 200.0);
857 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
858 }
859
860 fn wheel_delta_ticks(
861 ticks: i64,
862 physical_pixel: Option<f32>,
863 ) -> Option<mouse_binding::WheelDelta> {
864 Some(mouse_binding::WheelDelta {
865 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
866 physical_pixel,
867 })
868 }
869
870 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
871 Some(mouse_binding::WheelDelta {
872 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
873 physical_pixel,
874 })
875 }
876
877 #[test_case(
880 mouse_binding::MouseLocation::Relative(
881 mouse_binding::RelativeLocation {
882 millimeters: Position { x: 1.0, y: 2.0 }
883 }),
884 Position {
885 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
886 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
887 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
888 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
889 },
890 [
891 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
892 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
893 ]; "Valid move event."
894 )]
895 #[test_case(
896 mouse_binding::MouseLocation::Relative(
897 mouse_binding::RelativeLocation {
898 millimeters: Position {
899 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
900 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
901 }}),
902 Position {
903 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
904 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
905 },
906 [
907 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
908 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
909 ]; "Move event exceeds max bounds."
910 )]
911 #[test_case(
912 mouse_binding::MouseLocation::Relative(
913 mouse_binding::RelativeLocation {
914 millimeters: Position {
915 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
916 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
917 }}),
918 Position { x: 0.0, y: 0.0 },
919 [
920 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
921 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
922 ]; "Move event exceeds min bounds."
923 )]
924 #[fuchsia::test(allow_stalls = false)]
925 async fn move_event(
926 move_location: mouse_binding::MouseLocation,
927 expected_position: Position,
928 expected_relative_motion: [f32; 2],
929 ) {
930 let (configuration_proxy, mut configuration_request_stream) =
932 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
933 let (injector_registry_proxy, injector_registry_request_stream) =
934 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
935 let config_request_stream_fut =
936 handle_configuration_request_stream(&mut configuration_request_stream);
937
938 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
940 let inspector = fuchsia_inspect::Inspector::default();
941 let test_node = inspector.root().create_child("test_node");
942 let mouse_handler_fut = MouseInjectorHandler::new_handler(
943 configuration_proxy,
944 injector_registry_proxy,
945 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
946 sender,
947 &test_node,
948 metrics::MetricsLogger::default(),
949 );
950 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
951 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
952
953 let event_time = zx::MonotonicInstant::get();
954 let input_event = create_mouse_event(
955 move_location,
956 None, None, None, mouse_binding::MousePhase::Move,
960 HashSet::new(),
961 HashSet::new(),
962 event_time,
963 &DESCRIPTOR,
964 );
965
966 let handle_event_fut = mouse_handler.handle_input_event(input_event);
968 let expected_events = vec![
969 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
970 create_mouse_pointer_sample_event(
971 pointerinjector::EventPhase::Change,
972 vec![],
973 expected_position,
974 Some(expected_relative_motion),
975 None, None, None, event_time,
979 ),
980 ];
981
982 let (injector_stream_sender, injector_stream_receiver) =
986 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
987 let registry_fut = handle_registry_request_stream(
988 injector_registry_request_stream,
989 injector_stream_sender,
990 );
991 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
992
993 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
996 match receiver.next().await {
997 Some(CursorMessage::SetPosition(position)) => {
998 pretty_assertions::assert_eq!(position, expected_position);
999 }
1000 Some(CursorMessage::SetVisibility(_)) => {
1001 panic!("Received unexpected cursor visibility update.")
1002 }
1003 None => panic!("Did not receive cursor update."),
1004 }
1005
1006 assert_matches!(
1008 handle_result.as_slice(),
1009 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1010 );
1011 }
1012
1013 #[fuchsia::test(allow_stalls = false)]
1016 async fn move_absolute_event() {
1017 const DEVICE_ID: u32 = 1;
1018
1019 let (configuration_proxy, mut configuration_request_stream) =
1021 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1022 let (injector_registry_proxy, injector_registry_request_stream) =
1023 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1024 let config_request_stream_fut =
1025 handle_configuration_request_stream(&mut configuration_request_stream);
1026
1027 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1029 let inspector = fuchsia_inspect::Inspector::default();
1030 let test_node = inspector.root().create_child("test_node");
1031 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1032 configuration_proxy,
1033 injector_registry_proxy,
1034 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1035 sender,
1036 &test_node,
1037 metrics::MetricsLogger::default(),
1038 );
1039 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1040 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1041
1042 let cursor_location =
1058 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1059 let event_time = zx::MonotonicInstant::get();
1060 let descriptor =
1061 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1062 device_id: DEVICE_ID,
1063 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1064 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1065 wheel_v_range: None,
1066 wheel_h_range: None,
1067 buttons: None,
1068 counts_per_mm: COUNTS_PER_MM,
1069 });
1070 let input_event = create_mouse_event(
1071 cursor_location,
1072 None, None, None, mouse_binding::MousePhase::Move,
1076 HashSet::new(),
1077 HashSet::new(),
1078 event_time,
1079 &descriptor,
1080 );
1081
1082 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1084 let expected_position = Position {
1085 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1086 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1087 };
1088 let expected_events = vec![
1089 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1090 create_mouse_pointer_sample_event(
1091 pointerinjector::EventPhase::Change,
1092 vec![],
1093 expected_position,
1094 None, None, None, None, event_time,
1099 ),
1100 ];
1101
1102 let (injector_stream_sender, injector_stream_receiver) =
1106 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1107 let registry_fut = handle_registry_request_stream(
1108 injector_registry_request_stream,
1109 injector_stream_sender,
1110 );
1111 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1112
1113 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1116 match receiver.next().await {
1117 Some(CursorMessage::SetPosition(position)) => {
1118 assert_eq!(position, expected_position);
1119 }
1120 Some(CursorMessage::SetVisibility(_)) => {
1121 panic!("Received unexpected cursor visibility update.")
1122 }
1123 None => panic!("Did not receive cursor update."),
1124 }
1125
1126 assert_matches!(
1128 handle_result.as_slice(),
1129 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1130 );
1131 }
1132
1133 #[test_case(
1135 mouse_binding::MousePhase::Down,
1136 vec![1], vec![1]; "Down event injects button press state."
1137 )]
1138 #[test_case(
1139 mouse_binding::MousePhase::Up,
1140 vec![1], vec![]; "Up event injects button press state."
1141 )]
1142 #[fuchsia::test(allow_stalls = false)]
1143 async fn button_state_event(
1144 phase: mouse_binding::MousePhase,
1145 affected_buttons: Vec<mouse_binding::MouseButton>,
1146 pressed_buttons: Vec<mouse_binding::MouseButton>,
1147 ) {
1148 let (configuration_proxy, mut configuration_request_stream) =
1150 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1151 let (injector_registry_proxy, injector_registry_request_stream) =
1152 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1153 let config_request_stream_fut =
1154 handle_configuration_request_stream(&mut configuration_request_stream);
1155
1156 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1158 let inspector = fuchsia_inspect::Inspector::default();
1159 let test_node = inspector.root().create_child("test_node");
1160 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1161 configuration_proxy,
1162 injector_registry_proxy,
1163 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1164 sender,
1165 &test_node,
1166 metrics::MetricsLogger::default(),
1167 );
1168 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1169 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1170
1171 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1172 let event_time = zx::MonotonicInstant::get();
1173
1174 let input_event = create_mouse_event(
1175 cursor_location,
1176 None, None, None, phase,
1180 HashSet::from_iter(affected_buttons.clone()),
1181 HashSet::from_iter(pressed_buttons.clone()),
1182 event_time,
1183 &DESCRIPTOR,
1184 );
1185
1186 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1188 let expected_position = Position { x: 0.0, y: 0.0 };
1189 let expected_events = vec![
1190 create_mouse_pointer_sample_event_phase_add(
1191 pressed_buttons.clone(),
1192 expected_position,
1193 event_time,
1194 ),
1195 create_mouse_pointer_sample_event(
1196 pointerinjector::EventPhase::Change,
1197 pressed_buttons.clone(),
1198 expected_position,
1199 None, None, None, None, event_time,
1204 ),
1205 ];
1206
1207 let (injector_stream_sender, injector_stream_receiver) =
1211 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1212 let registry_fut = handle_registry_request_stream(
1213 injector_registry_request_stream,
1214 injector_stream_sender,
1215 );
1216 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1217
1218 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1221 match receiver.next().await {
1222 Some(CursorMessage::SetPosition(position)) => {
1223 pretty_assertions::assert_eq!(position, expected_position);
1224 }
1225 Some(CursorMessage::SetVisibility(_)) => {
1226 panic!("Received unexpected cursor visibility update.")
1227 }
1228 None => panic!("Did not receive cursor update."),
1229 }
1230
1231 assert_matches!(
1233 handle_result.as_slice(),
1234 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1235 );
1236 }
1237
1238 #[fuchsia::test(allow_stalls = false)]
1240 async fn down_up_event() {
1241 let (configuration_proxy, mut configuration_request_stream) =
1243 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1244 let (injector_registry_proxy, injector_registry_request_stream) =
1245 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1246 let config_request_stream_fut =
1247 handle_configuration_request_stream(&mut configuration_request_stream);
1248
1249 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1253 let inspector = fuchsia_inspect::Inspector::default();
1254 let test_node = inspector.root().create_child("test_node");
1255 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1256 configuration_proxy,
1257 injector_registry_proxy,
1258 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1259 sender,
1260 &test_node,
1261 metrics::MetricsLogger::default(),
1262 );
1263 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1264 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1265
1266 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1267 let event_time1 = zx::MonotonicInstant::get();
1268 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1269
1270 let event1 = create_mouse_event(
1271 cursor_location,
1272 None, None, None, mouse_binding::MousePhase::Down,
1276 HashSet::from_iter(vec![1]),
1277 HashSet::from_iter(vec![1]),
1278 event_time1,
1279 &DESCRIPTOR,
1280 );
1281
1282 let event2 = create_mouse_event(
1283 cursor_location,
1284 None, None, None, mouse_binding::MousePhase::Up,
1288 HashSet::from_iter(vec![1]),
1289 HashSet::new(),
1290 event_time2,
1291 &DESCRIPTOR,
1292 );
1293
1294 let expected_position = Position { x: 0.0, y: 0.0 };
1295
1296 let (injector_stream_sender, injector_stream_receiver) =
1300 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1301 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1303 let registry_fut = handle_registry_request_stream2(
1304 injector_registry_request_stream,
1305 injector_stream_sender,
1306 );
1307
1308 let _registry_task = fasync::Task::local(registry_fut);
1310
1311 mouse_handler.clone().handle_input_event(event1).await;
1312 assert_eq!(
1313 injector_stream_receiver.next().await.map(|events| events.concat()),
1314 Some(vec![
1315 create_mouse_pointer_sample_event_phase_add(
1316 vec![1],
1317 expected_position,
1318 event_time1,
1319 ),
1320 create_mouse_pointer_sample_event(
1321 pointerinjector::EventPhase::Change,
1322 vec![1],
1323 expected_position,
1324 None, None, None, None, event_time1,
1329 )
1330 ])
1331 );
1332
1333 mouse_handler.clone().handle_input_event(event2).await;
1335 assert_eq!(
1336 injector_stream_receiver.next().await.map(|events| events.concat()),
1337 Some(vec![create_mouse_pointer_sample_event(
1338 pointerinjector::EventPhase::Change,
1339 vec![],
1340 expected_position,
1341 None, None, None, None, event_time2,
1346 )])
1347 );
1348
1349 match receiver.next().await {
1351 Some(CursorMessage::SetPosition(position)) => {
1352 assert_eq!(position, expected_position);
1353 }
1354 Some(CursorMessage::SetVisibility(_)) => {
1355 panic!("Received unexpected cursor visibility update.")
1356 }
1357 None => panic!("Did not receive cursor update."),
1358 }
1359 }
1360
1361 #[fuchsia::test(allow_stalls = false)]
1371 async fn down_down_up_up_event() {
1372 let (configuration_proxy, mut configuration_request_stream) =
1374 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1375 let (injector_registry_proxy, injector_registry_request_stream) =
1376 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1377 let config_request_stream_fut =
1378 handle_configuration_request_stream(&mut configuration_request_stream);
1379
1380 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1384 let inspector = fuchsia_inspect::Inspector::default();
1385 let test_node = inspector.root().create_child("test_node");
1386 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1387 configuration_proxy,
1388 injector_registry_proxy,
1389 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1390 sender,
1391 &test_node,
1392 metrics::MetricsLogger::default(),
1393 );
1394 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1395 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1396
1397 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1398 let event_time1 = zx::MonotonicInstant::get();
1399 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1400 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1401 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1402
1403 let event1 = create_mouse_event(
1404 cursor_location,
1405 None, None, None, mouse_binding::MousePhase::Down,
1409 HashSet::from_iter(vec![1]),
1410 HashSet::from_iter(vec![1]),
1411 event_time1,
1412 &DESCRIPTOR,
1413 );
1414 let event2 = create_mouse_event(
1415 cursor_location,
1416 None, None, None, mouse_binding::MousePhase::Down,
1420 HashSet::from_iter(vec![2]),
1421 HashSet::from_iter(vec![1, 2]),
1422 event_time2,
1423 &DESCRIPTOR,
1424 );
1425 let event3 = create_mouse_event(
1426 cursor_location,
1427 None, None, None, mouse_binding::MousePhase::Up,
1431 HashSet::from_iter(vec![1]),
1432 HashSet::from_iter(vec![2]),
1433 event_time3,
1434 &DESCRIPTOR,
1435 );
1436 let event4 = create_mouse_event(
1437 cursor_location,
1438 None, None, None, mouse_binding::MousePhase::Up,
1442 HashSet::from_iter(vec![2]),
1443 HashSet::new(),
1444 event_time4,
1445 &DESCRIPTOR,
1446 );
1447
1448 let expected_position = Position { x: 0.0, y: 0.0 };
1449
1450 let (injector_stream_sender, injector_stream_receiver) =
1454 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1455 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1457 let registry_fut = handle_registry_request_stream2(
1458 injector_registry_request_stream,
1459 injector_stream_sender,
1460 );
1461
1462 let _registry_task = fasync::Task::local(registry_fut);
1464 mouse_handler.clone().handle_input_event(event1).await;
1465 assert_eq!(
1466 injector_stream_receiver.next().await.map(|events| events.concat()),
1467 Some(vec![
1468 create_mouse_pointer_sample_event_phase_add(
1469 vec![1],
1470 expected_position,
1471 event_time1,
1472 ),
1473 create_mouse_pointer_sample_event(
1474 pointerinjector::EventPhase::Change,
1475 vec![1],
1476 expected_position,
1477 None, None, None, None, event_time1,
1482 )
1483 ])
1484 );
1485
1486 mouse_handler.clone().handle_input_event(event2).await;
1488 let pointer_sample_event2 = injector_stream_receiver
1489 .next()
1490 .await
1491 .map(|events| events.concat())
1492 .expect("Failed to receive pointer sample event.");
1493 let expected_event_time: i64 = event_time2.into_nanos();
1494 assert_eq!(pointer_sample_event2.len(), 1);
1495
1496 match &pointer_sample_event2[0] {
1499 pointerinjector::Event {
1500 timestamp: Some(actual_event_time),
1501 data:
1502 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1503 pointer_id: Some(0),
1504 phase: Some(pointerinjector::EventPhase::Change),
1505 position_in_viewport: Some(actual_position),
1506 scroll_v: None,
1507 scroll_h: None,
1508 pressed_buttons: Some(actual_buttons),
1509 relative_motion: None,
1510 ..
1511 })),
1512 ..
1513 } => {
1514 assert_eq!(actual_event_time, &expected_event_time);
1515 assert_eq!(actual_position[0], expected_position.x);
1516 assert_eq!(actual_position[1], expected_position.y);
1517 assert_eq!(
1518 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1519 HashSet::from_iter(vec![1, 2])
1520 );
1521 }
1522 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1523 }
1524
1525 mouse_handler.clone().handle_input_event(event3).await;
1527 assert_eq!(
1528 injector_stream_receiver.next().await.map(|events| events.concat()),
1529 Some(vec![create_mouse_pointer_sample_event(
1530 pointerinjector::EventPhase::Change,
1531 vec![2],
1532 expected_position,
1533 None, None, None, None, event_time3,
1538 )])
1539 );
1540
1541 mouse_handler.clone().handle_input_event(event4).await;
1543 assert_eq!(
1544 injector_stream_receiver.next().await.map(|events| events.concat()),
1545 Some(vec![create_mouse_pointer_sample_event(
1546 pointerinjector::EventPhase::Change,
1547 vec![],
1548 expected_position,
1549 None, None, None, None, event_time4,
1554 )])
1555 );
1556
1557 match receiver.next().await {
1559 Some(CursorMessage::SetPosition(position)) => {
1560 assert_eq!(position, expected_position);
1561 }
1562 Some(CursorMessage::SetVisibility(_)) => {
1563 panic!("Received unexpected cursor visibility update.")
1564 }
1565 None => panic!("Did not receive cursor update."),
1566 }
1567 }
1568
1569 #[fuchsia::test(allow_stalls = false)]
1571 async fn down_move_up_event() {
1572 let (configuration_proxy, mut configuration_request_stream) =
1574 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1575 let (injector_registry_proxy, injector_registry_request_stream) =
1576 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1577 let config_request_stream_fut =
1578 handle_configuration_request_stream(&mut configuration_request_stream);
1579
1580 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1584 let inspector = fuchsia_inspect::Inspector::default();
1585 let test_node = inspector.root().create_child("test_node");
1586 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1587 configuration_proxy,
1588 injector_registry_proxy,
1589 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1590 sender,
1591 &test_node,
1592 metrics::MetricsLogger::default(),
1593 );
1594 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1595 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1596
1597 let event_time1 = zx::MonotonicInstant::get();
1598 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1599 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1600 let zero_position = Position { x: 0.0, y: 0.0 };
1601 let expected_position = Position {
1602 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1603 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1604 };
1605 let expected_relative_motion = [
1606 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1607 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1608 ];
1609 let event1 = create_mouse_event(
1610 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1611 None, None, None, mouse_binding::MousePhase::Down,
1615 HashSet::from_iter(vec![1]),
1616 HashSet::from_iter(vec![1]),
1617 event_time1,
1618 &DESCRIPTOR,
1619 );
1620 let event2 = create_mouse_event(
1621 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1622 millimeters: Position { x: 10.0, y: 5.0 },
1623 }),
1624 None, None, None, mouse_binding::MousePhase::Move,
1628 HashSet::from_iter(vec![1]),
1629 HashSet::from_iter(vec![1]),
1630 event_time2,
1631 &DESCRIPTOR,
1632 );
1633 let event3 = create_mouse_event(
1634 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1635 millimeters: Position { x: 0.0, y: 0.0 },
1636 }),
1637 None, None, None, mouse_binding::MousePhase::Up,
1641 HashSet::from_iter(vec![1]),
1642 HashSet::from_iter(vec![]),
1643 event_time3,
1644 &DESCRIPTOR,
1645 );
1646
1647 let (injector_stream_sender, injector_stream_receiver) =
1651 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1652 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1654 let registry_fut = handle_registry_request_stream2(
1655 injector_registry_request_stream,
1656 injector_stream_sender,
1657 );
1658
1659 let _registry_task = fasync::Task::local(registry_fut);
1661 mouse_handler.clone().handle_input_event(event1).await;
1662 assert_eq!(
1663 injector_stream_receiver.next().await.map(|events| events.concat()),
1664 Some(vec![
1665 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1666 create_mouse_pointer_sample_event(
1667 pointerinjector::EventPhase::Change,
1668 vec![1],
1669 zero_position,
1670 None, None, None, None, event_time1,
1675 )
1676 ])
1677 );
1678
1679 match receiver.next().await {
1681 Some(CursorMessage::SetPosition(position)) => {
1682 assert_eq!(position, zero_position);
1683 }
1684 Some(CursorMessage::SetVisibility(_)) => {
1685 panic!("Received unexpected cursor visibility update.")
1686 }
1687 None => panic!("Did not receive cursor update."),
1688 }
1689
1690 mouse_handler.clone().handle_input_event(event2).await;
1692 assert_eq!(
1693 injector_stream_receiver.next().await.map(|events| events.concat()),
1694 Some(vec![create_mouse_pointer_sample_event(
1695 pointerinjector::EventPhase::Change,
1696 vec![1],
1697 expected_position,
1698 Some(expected_relative_motion),
1699 None, None, None, event_time2,
1703 )])
1704 );
1705
1706 match receiver.next().await {
1708 Some(CursorMessage::SetPosition(position)) => {
1709 assert_eq!(position, expected_position);
1710 }
1711 Some(CursorMessage::SetVisibility(_)) => {
1712 panic!("Received unexpected cursor visibility update.")
1713 }
1714 None => panic!("Did not receive cursor update."),
1715 }
1716
1717 mouse_handler.clone().handle_input_event(event3).await;
1719 assert_eq!(
1720 injector_stream_receiver.next().await.map(|events| events.concat()),
1721 Some(vec![create_mouse_pointer_sample_event(
1722 pointerinjector::EventPhase::Change,
1723 vec![],
1724 expected_position,
1725 None, None, None, None, event_time3,
1730 )])
1731 );
1732
1733 match receiver.next().await {
1735 Some(CursorMessage::SetPosition(position)) => {
1736 assert_eq!(position, expected_position);
1737 }
1738 Some(CursorMessage::SetVisibility(_)) => {
1739 panic!("Received unexpected cursor visibility update.")
1740 }
1741 None => panic!("Did not receive cursor update."),
1742 }
1743 }
1744
1745 #[fuchsia::test(allow_stalls = false)]
1747 async fn handler_ignores_handled_events() {
1748 let (configuration_proxy, mut configuration_request_stream) =
1750 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1751 let (injector_registry_proxy, injector_registry_request_stream) =
1752 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1753 let config_request_stream_fut =
1754 handle_configuration_request_stream(&mut configuration_request_stream);
1755
1756 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1758 let inspector = fuchsia_inspect::Inspector::default();
1759 let test_node = inspector.root().create_child("test_node");
1760 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1761 configuration_proxy,
1762 injector_registry_proxy,
1763 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1764 sender,
1765 &test_node,
1766 metrics::MetricsLogger::default(),
1767 );
1768 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1769 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1770
1771 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1772 let cursor_location =
1773 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1774 millimeters: Position {
1775 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1776 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1777 },
1778 });
1779 let event_time = zx::MonotonicInstant::get();
1780 let input_events = vec![create_mouse_event_with_handled(
1781 cursor_location,
1782 None, None, None, mouse_binding::MousePhase::Move,
1786 HashSet::new(),
1787 HashSet::new(),
1788 event_time,
1789 &DESCRIPTOR,
1790 input_device::Handled::Yes,
1791 )];
1792
1793 assert_handler_ignores_input_event_sequence(
1794 mouse_handler,
1795 input_events,
1796 injector_registry_request_stream,
1797 )
1798 .await;
1799
1800 assert!(receiver.next().await.is_none());
1802 }
1803
1804 fn zero_relative_location() -> mouse_binding::MouseLocation {
1805 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1806 millimeters: Position { x: 0.0, y: 0.0 },
1807 })
1808 }
1809
1810 #[test_case(
1811 create_mouse_event(
1812 zero_relative_location(),
1813 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1817 HashSet::new(),
1818 HashSet::new(),
1819 zx::MonotonicInstant::ZERO,
1820 &DESCRIPTOR,
1821 ),
1822 create_mouse_pointer_sample_event(
1823 pointerinjector::EventPhase::Change,
1824 vec![],
1825 Position { x: 50.0, y: 50.0 },
1826 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1831 ); "v tick scroll"
1832 )]
1833 #[test_case(
1834 create_mouse_event(
1835 zero_relative_location(),
1836 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1840 HashSet::new(),
1841 HashSet::new(),
1842 zx::MonotonicInstant::ZERO,
1843 &DESCRIPTOR,
1844 ),
1845 create_mouse_pointer_sample_event(
1846 pointerinjector::EventPhase::Change,
1847 vec![],
1848 Position { x: 50.0, y: 50.0 },
1849 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1854 ); "h tick scroll"
1855 )]
1856 #[test_case(
1857 create_mouse_event(
1858 zero_relative_location(),
1859 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1863 HashSet::new(),
1864 HashSet::new(),
1865 zx::MonotonicInstant::ZERO,
1866 &DESCRIPTOR,
1867 ),
1868 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1869 pointerinjector::EventPhase::Change,
1870 vec![],
1871 Position { x: 50.0, y: 50.0 },
1872 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1879 ); "v tick scroll with physical pixel"
1880 )]
1881 #[test_case(
1882 create_mouse_event(
1883 zero_relative_location(),
1884 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1888 HashSet::new(),
1889 HashSet::new(),
1890 zx::MonotonicInstant::ZERO,
1891 &DESCRIPTOR,
1892 ),
1893 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1894 pointerinjector::EventPhase::Change,
1895 vec![],
1896 Position { x: 50.0, y: 50.0 },
1897 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1904 ); "h tick scroll with physical pixel"
1905 )]
1906 #[test_case(
1907 create_mouse_event(
1908 zero_relative_location(),
1909 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1913 HashSet::new(),
1914 HashSet::new(),
1915 zx::MonotonicInstant::ZERO,
1916 &DESCRIPTOR,
1917 ),
1918 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1919 pointerinjector::EventPhase::Change,
1920 vec![],
1921 Position { x: 50.0, y: 50.0 },
1922 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1929 ); "v mm scroll with physical pixel"
1930 )]
1931 #[test_case(
1932 create_mouse_event(
1933 zero_relative_location(),
1934 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1938 HashSet::new(),
1939 HashSet::new(),
1940 zx::MonotonicInstant::ZERO,
1941 &DESCRIPTOR,
1942 ),
1943 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1944 pointerinjector::EventPhase::Change,
1945 vec![],
1946 Position { x: 50.0, y: 50.0 },
1947 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1954 ); "h mm scroll with physical pixel"
1955 )]
1956 #[fuchsia::test(allow_stalls = false)]
1958 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1959 let (configuration_proxy, mut configuration_request_stream) =
1961 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1962 let (injector_registry_proxy, injector_registry_request_stream) =
1963 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1964 let config_request_stream_fut =
1965 handle_configuration_request_stream(&mut configuration_request_stream);
1966
1967 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1969 let inspector = fuchsia_inspect::Inspector::default();
1970 let test_node = inspector.root().create_child("test_node");
1971 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1972 configuration_proxy,
1973 injector_registry_proxy,
1974 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1975 sender,
1976 &test_node,
1977 metrics::MetricsLogger::default(),
1978 );
1979 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1980 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1981
1982 let (injector_stream_sender, injector_stream_receiver) =
1986 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1987 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1989 let registry_fut = handle_registry_request_stream2(
1990 injector_registry_request_stream,
1991 injector_stream_sender,
1992 );
1993
1994 let event_time = zx::MonotonicInstant::get();
1995
1996 let event = input_device::InputEvent { event_time, ..event };
1997
1998 let want_event =
1999 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2000
2001 let _registry_task = fasync::Task::local(registry_fut);
2003
2004 mouse_handler.clone().handle_input_event(event).await;
2005 let got_events =
2006 injector_stream_receiver.next().await.map(|events| events.concat()).unwrap();
2007 pretty_assertions::assert_eq!(got_events.len(), 2);
2008 assert_matches!(
2009 got_events[0],
2010 pointerinjector::Event {
2011 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2012 phase: Some(pointerinjector::EventPhase::Add),
2013 ..
2014 })),
2015 ..
2016 }
2017 );
2018
2019 pretty_assertions::assert_eq!(got_events[1], want_event);
2020 }
2021
2022 #[fuchsia::test(allow_stalls = false)]
2024 async fn down_scroll_up_scroll() {
2025 let (configuration_proxy, mut configuration_request_stream) =
2027 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2028 let (injector_registry_proxy, injector_registry_request_stream) =
2029 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2030 let config_request_stream_fut =
2031 handle_configuration_request_stream(&mut configuration_request_stream);
2032
2033 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2035 let inspector = fuchsia_inspect::Inspector::default();
2036 let test_node = inspector.root().create_child("test_node");
2037 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2038 configuration_proxy,
2039 injector_registry_proxy,
2040 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2041 sender,
2042 &test_node,
2043 metrics::MetricsLogger::default(),
2044 );
2045 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2046 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2047
2048 let (injector_stream_sender, injector_stream_receiver) =
2052 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2053 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2055 let registry_fut = handle_registry_request_stream2(
2056 injector_registry_request_stream,
2057 injector_stream_sender,
2058 );
2059
2060 let event_time1 = zx::MonotonicInstant::get();
2061 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2062 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2063 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2064
2065 let _registry_task = fasync::Task::local(registry_fut);
2067
2068 let zero_location =
2069 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2070 millimeters: Position { x: 0.0, y: 0.0 },
2071 });
2072 let expected_position = Position { x: 50.0, y: 50.0 };
2073
2074 let down_event = create_mouse_event(
2075 zero_location,
2076 None, None, None, mouse_binding::MousePhase::Down,
2080 HashSet::from_iter(vec![1]),
2081 HashSet::from_iter(vec![1]),
2082 event_time1,
2083 &DESCRIPTOR,
2084 );
2085
2086 let wheel_event = create_mouse_event(
2087 zero_location,
2088 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2092 HashSet::from_iter(vec![1]),
2093 HashSet::from_iter(vec![1]),
2094 event_time2,
2095 &DESCRIPTOR,
2096 );
2097
2098 let up_event = create_mouse_event(
2099 zero_location,
2100 None,
2101 None,
2102 None, mouse_binding::MousePhase::Up,
2104 HashSet::from_iter(vec![1]),
2105 HashSet::new(),
2106 event_time3,
2107 &DESCRIPTOR,
2108 );
2109
2110 let continue_wheel_event = create_mouse_event(
2111 zero_location,
2112 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2116 HashSet::new(),
2117 HashSet::new(),
2118 event_time4,
2119 &DESCRIPTOR,
2120 );
2121
2122 mouse_handler.clone().handle_input_event(down_event).await;
2124 assert_eq!(
2125 injector_stream_receiver.next().await.map(|events| events.concat()),
2126 Some(vec![
2127 create_mouse_pointer_sample_event_phase_add(
2128 vec![1],
2129 expected_position,
2130 event_time1,
2131 ),
2132 create_mouse_pointer_sample_event(
2133 pointerinjector::EventPhase::Change,
2134 vec![1],
2135 expected_position,
2136 None, None, None, None, event_time1,
2141 ),
2142 ])
2143 );
2144
2145 mouse_handler.clone().handle_input_event(wheel_event).await;
2147 assert_eq!(
2148 injector_stream_receiver.next().await.map(|events| events.concat()),
2149 Some(vec![create_mouse_pointer_sample_event(
2150 pointerinjector::EventPhase::Change,
2151 vec![1],
2152 expected_position,
2153 None, Some(1), None, Some(false), event_time2,
2158 )])
2159 );
2160
2161 mouse_handler.clone().handle_input_event(up_event).await;
2163 assert_eq!(
2164 injector_stream_receiver.next().await.map(|events| events.concat()),
2165 Some(vec![create_mouse_pointer_sample_event(
2166 pointerinjector::EventPhase::Change,
2167 vec![],
2168 expected_position,
2169 None, None, None, None, event_time3,
2174 )])
2175 );
2176
2177 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2179 assert_eq!(
2180 injector_stream_receiver.next().await.map(|events| events.concat()),
2181 Some(vec![create_mouse_pointer_sample_event(
2182 pointerinjector::EventPhase::Change,
2183 vec![],
2184 expected_position,
2185 None, Some(1), None, Some(false), event_time4,
2190 )])
2191 );
2192 }
2193
2194 #[fuchsia::test(allow_stalls = false)]
2195 async fn mouse_injector_handler_initialized_with_inspect_node() {
2196 let (configuration_proxy, mut configuration_request_stream) =
2197 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2198 let config_request_stream_fut =
2199 handle_configuration_request_stream(&mut configuration_request_stream);
2200 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2201 let inspector = fuchsia_inspect::Inspector::default();
2202 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2203 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2204 configuration_proxy,
2205 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2206 sender,
2207 &fake_handlers_node,
2208 metrics::MetricsLogger::default(),
2209 );
2210 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2211 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2212
2213 diagnostics_assertions::assert_data_tree!(inspector, root: {
2214 input_handlers_node: {
2215 mouse_injector_handler: {
2216 events_received_count: 0u64,
2217 events_handled_count: 0u64,
2218 last_received_timestamp_ns: 0u64,
2219 "fuchsia.inspect.Health": {
2220 status: "STARTING_UP",
2221 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2224 },
2225 }
2226 }
2227 });
2228 }
2229
2230 #[fuchsia::test(allow_stalls = false)]
2231 async fn mouse_injector_handler_inspect_counts_events() {
2232 let (configuration_proxy, mut configuration_request_stream) =
2234 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2235 let (injector_registry_proxy, injector_registry_request_stream) =
2236 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2237 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2238
2239 let inspector = fuchsia_inspect::Inspector::default();
2240 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2241
2242 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2244 configuration_proxy,
2245 injector_registry_proxy,
2246 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2247 sender,
2248 &fake_handlers_node,
2249 metrics::MetricsLogger::default(),
2250 );
2251 let config_request_stream_fut =
2252 handle_configuration_request_stream(&mut configuration_request_stream);
2253
2254 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2255 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2256
2257 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2258 let event_time1 = zx::MonotonicInstant::get();
2259 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2260 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2261
2262 let input_events = vec![
2263 create_mouse_event(
2264 cursor_location,
2265 None, None, None, mouse_binding::MousePhase::Down,
2269 HashSet::from_iter(vec![1]),
2270 HashSet::from_iter(vec![1]),
2271 event_time1,
2272 &DESCRIPTOR,
2273 ),
2274 create_mouse_event(
2275 cursor_location,
2276 None, None, None, mouse_binding::MousePhase::Up,
2280 HashSet::from_iter(vec![1]),
2281 HashSet::new(),
2282 event_time2,
2283 &DESCRIPTOR,
2284 ),
2285 create_mouse_event_with_handled(
2286 cursor_location,
2287 None, None, None, mouse_binding::MousePhase::Down,
2291 HashSet::from_iter(vec![1]),
2292 HashSet::from_iter(vec![1]),
2293 event_time3,
2294 &DESCRIPTOR,
2295 input_device::Handled::Yes,
2296 ),
2297 ];
2298
2299 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2303 let registry_fut = handle_registry_request_stream2(
2304 injector_registry_request_stream,
2305 injector_stream_sender,
2306 );
2307
2308 let _registry_task = fasync::Task::local(registry_fut);
2310 for input_event in input_events {
2311 mouse_handler.clone().handle_input_event(input_event).await;
2312 }
2313
2314 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2315
2316 diagnostics_assertions::assert_data_tree!(inspector, root: {
2317 input_handlers_node: {
2318 mouse_injector_handler: {
2319 events_received_count: 2u64,
2320 events_handled_count: 2u64,
2321 last_received_timestamp_ns: last_received_event_time,
2322 "fuchsia.inspect.Health": {
2323 status: "STARTING_UP",
2324 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2327 },
2328 }
2329 }
2330 });
2331 }
2332}