1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{Handler, InputHandler, InputHandlerStatus};
8use crate::utils::{self, CursorMessage, Position, Size};
9use crate::{
10 Dispatcher, Incoming, MonotonicInstant, Transport, input_device, metrics, mouse_binding,
11};
12use anyhow::{Context, Error, Result, anyhow};
13use async_trait::async_trait;
14use async_utils::hanging_get::client::HangingGetStream;
15use fidl_fuchsia_input_report::Range;
16use fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config;
17use fidl_next_fuchsia_ui_pointerinjector as pointerinjector;
18use fuchsia_inspect::health::Reporter;
19use futures::SinkExt;
20use futures::channel::mpsc::Sender;
21use futures::stream::StreamExt;
22use metrics_registry::*;
23use sorted_vec_map::SortedVecMap;
24use std::cell::{Ref, RefCell, RefMut};
25use std::rc::Rc;
26
27pub struct MouseInjectorHandler {
30 mutable_state: RefCell<MutableState>,
32
33 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
36
37 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
40
41 max_position: Position,
44
45 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
47
48 configuration_proxy: pointerinjector_config::SetupProxy,
50
51 pub inspect_status: InputHandlerStatus,
53
54 metrics_logger: metrics::MetricsLogger,
55}
56
57struct MutableState {
58 viewport: Option<pointerinjector::Viewport>,
61
62 injectors: SortedVecMap<u32, fidl_next::Client<pointerinjector::Device, Transport>>,
64
65 current_position: Position,
67
68 cursor_message_sender: Sender<CursorMessage>,
70}
71
72impl Handler for MouseInjectorHandler {
73 fn set_handler_healthy(self: std::rc::Rc<Self>) {
74 self.inspect_status.health_node.borrow_mut().set_ok();
75 }
76
77 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
78 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
79 }
80
81 fn get_name(&self) -> &'static str {
82 "MouseInjectorHandler"
83 }
84
85 fn interest(&self) -> Vec<input_device::InputEventType> {
86 vec![input_device::InputEventType::Mouse]
87 }
88}
89
90#[async_trait(?Send)]
91impl InputHandler for MouseInjectorHandler {
92 async fn handle_input_event(
93 self: Rc<Self>,
94 mut input_event: input_device::InputEvent,
95 ) -> Vec<input_device::InputEvent> {
96 fuchsia_trace::duration!("input", "mouse_injector_handler");
97 match input_event {
98 input_device::InputEvent {
99 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
100 device_descriptor:
101 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
102 event_time,
103 handled: input_device::Handled::No,
104 trace_id,
105 } => {
106 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
107 let trace_id = match trace_id {
108 Some(id) => {
109 fuchsia_trace::flow_step!("input", "event_in_input_pipeline", id.into());
110 id
111 }
112 None => fuchsia_trace::Id::new(),
113 };
114
115 self.inspect_status.count_received_event(&event_time);
116 if let Err(e) =
118 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
119 {
120 self.metrics_logger.log_error(
121 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
122 std::format!("update_cursor_renderer failed: {}", e));
123 }
124
125 if let Err(e) = self
127 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
128 .await
129 {
130 self.metrics_logger.log_error(
131 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
132 std::format!("ensure_injector_registered failed: {}", e));
133 }
134
135 if let Err(e) = self
137 .send_event_to_scenic(
138 &mouse_event,
139 &mouse_device_descriptor,
140 event_time,
141 trace_id.into(),
142 )
143 .await
144 {
145 self.metrics_logger.log_error(
146 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
147 std::format!("send_event_to_scenic failed: {}", e));
148 }
149
150 input_event.handled = input_device::Handled::Yes;
152 self.inspect_status.count_handled_event();
153 }
154 _ => {
155 self.metrics_logger.log_error(
156 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
157 std::format!(
158 "{} uninterested input event: {:?}",
159 self.get_name(),
160 input_event.get_event_type()
161 ),
162 );
163 }
164 }
165 vec![input_event]
166 }
167}
168
169impl MouseInjectorHandler {
170 pub async fn new(
183 incoming: &Incoming,
184 display_size: Size,
185 cursor_message_sender: Sender<CursorMessage>,
186 input_handlers_node: &fuchsia_inspect::Node,
187 metrics_logger: metrics::MetricsLogger,
188 ) -> Result<Rc<Self>, Error> {
189 let configuration_proxy =
190 incoming.connect_protocol::<pointerinjector_config::SetupProxy>()?;
191 let injector_registry_proxy =
192 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
193
194 Self::new_handler(
195 configuration_proxy,
196 injector_registry_proxy,
197 display_size,
198 cursor_message_sender,
199 input_handlers_node,
200 metrics_logger,
201 )
202 .await
203 }
204
205 pub async fn new_with_config_proxy(
221 incoming: &Incoming,
222 configuration_proxy: pointerinjector_config::SetupProxy,
223 display_size: Size,
224 cursor_message_sender: Sender<CursorMessage>,
225 input_handlers_node: &fuchsia_inspect::Node,
226 metrics_logger: metrics::MetricsLogger,
227 ) -> Result<Rc<Self>, Error> {
228 let injector_registry_proxy =
229 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
230 Self::new_handler(
231 configuration_proxy,
232 injector_registry_proxy,
233 display_size,
234 cursor_message_sender,
235 input_handlers_node,
236 metrics_logger,
237 )
238 .await
239 }
240
241 fn inner(&self) -> Ref<'_, MutableState> {
242 self.mutable_state.borrow()
243 }
244
245 fn inner_mut(&self) -> RefMut<'_, MutableState> {
246 self.mutable_state.borrow_mut()
247 }
248
249 async fn new_handler(
265 configuration_proxy: pointerinjector_config::SetupProxy,
266 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
267 display_size: Size,
268 cursor_message_sender: Sender<CursorMessage>,
269 input_handlers_node: &fuchsia_inspect::Node,
270 metrics_logger: metrics::MetricsLogger,
271 ) -> Result<Rc<Self>, Error> {
272 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
274 let inspect_status = InputHandlerStatus::new(
275 input_handlers_node,
276 "mouse_injector_handler",
277 false,
278 );
279 let handler = Rc::new(Self {
280 mutable_state: RefCell::new(MutableState {
281 viewport: None,
282 injectors: SortedVecMap::new(),
283 current_position: Position {
285 x: display_size.width / 2.0,
286 y: display_size.height / 2.0,
287 },
288 cursor_message_sender,
289 }),
290 context_view_ref,
291 target_view_ref,
292 max_position: Position { x: display_size.width, y: display_size.height },
293 injector_registry_proxy,
294 configuration_proxy,
295 inspect_status,
296 metrics_logger,
297 });
298
299 Ok(handler)
300 }
301
302 async fn ensure_injector_registered(
310 self: &Rc<Self>,
311 mouse_event: &mouse_binding::MouseEvent,
312 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
313 event_time: zx::MonotonicInstant,
314 ) -> Result<(), anyhow::Error> {
315 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
316 return Ok(());
317 }
318
319 let (device_proxy, device_server) =
321 fidl_next::fuchsia::create_channel::<pointerinjector::Device>();
322 let device_proxy = Dispatcher::client_from_zx_channel(device_proxy).spawn();
323 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
324 .context("Failed to duplicate context view ref.")?;
325 let context = fidl_next_fuchsia_ui_views::ViewRef { reference: context.reference };
326 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
327 .context("Failed to duplicate target view ref.")?;
328 let target = fidl_next_fuchsia_ui_views::ViewRef { reference: target.reference };
329
330 let viewport = self.inner().viewport.clone();
331 let config = pointerinjector::Config {
332 device_id: Some(mouse_descriptor.device_id),
333 device_type: Some(pointerinjector::DeviceType::Mouse),
334 context: Some(pointerinjector::Context::View(context)),
335 target: Some(pointerinjector::Target::View(target)),
336 viewport,
337 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
338 scroll_v_range: utils::axis_to_next(mouse_descriptor.wheel_v_range.as_ref()),
339 scroll_h_range: utils::axis_to_next(mouse_descriptor.wheel_h_range.as_ref()),
340 buttons: mouse_descriptor.buttons.clone(),
341 ..Default::default()
342 };
343
344 self.injector_registry_proxy
346 .register(config, device_server)
347 .await
348 .context("Failed to register injector.")?;
349 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
350
351 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
353
354 let events_to_send = vec![self.create_pointer_sample_event(
356 mouse_event,
357 event_time,
358 pointerinjector::EventPhase::Add,
359 self.inner().current_position,
360 None,
361 None,
362 )];
363 device_proxy
364 .inject_events(events_to_send)
365 .send_immediately()
366 .context("Failed to ADD new MouseDevice.")?;
367
368 Ok(())
369 }
370
371 async fn update_cursor_renderer(
382 &self,
383 mouse_event: &mouse_binding::MouseEvent,
384 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
385 ) -> Result<(), anyhow::Error> {
386 let mut new_position = match (mouse_event.location, mouse_descriptor) {
387 (
388 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation { counts }),
389 _,
390 ) => self.inner().current_position + counts,
391 (
392 mouse_binding::MouseLocation::Absolute(position),
393 mouse_binding::MouseDeviceDescriptor {
394 absolute_x_range: Some(x_range),
395 absolute_y_range: Some(y_range),
396 ..
397 },
398 ) => self.scale_absolute_position(&position, &x_range, &y_range),
399 (mouse_binding::MouseLocation::Absolute(_), _) => {
400 return Err(anyhow!(
401 "Received an Absolute mouse location without absolute device ranges."
402 ));
403 }
404 };
405 Position::clamp(&mut new_position, Position::zero(), self.max_position);
406 self.inner_mut().current_position = new_position;
407
408 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
409 cursor_message_sender
410 .send(CursorMessage::SetPosition(new_position))
411 .await
412 .context("Failed to send current mouse position to cursor renderer")?;
413
414 Ok(())
415 }
416
417 fn scale_absolute_position(
425 &self,
426 position: &Position,
427 x_range: &Range,
428 y_range: &Range,
429 ) -> Position {
430 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
431 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
432 self.max_position * ((*position - range_min) / (range_max - range_min))
433 }
434
435 async fn send_event_to_scenic(
442 &self,
443 mouse_event: &mouse_binding::MouseEvent,
444 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
445 event_time: zx::MonotonicInstant,
446 tracing_id: u64,
447 ) -> Result<(), anyhow::Error> {
448 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
449 if let Some(injector) = injector {
450 let relative_motion = match mouse_event.location {
451 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
452 counts: offset_counts,
453 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
454 Some([offset_counts.x, offset_counts.y])
455 }
456 _ => None,
457 };
458 let events_to_send = vec![self.create_pointer_sample_event(
459 mouse_event,
460 event_time,
461 pointerinjector::EventPhase::Change,
462 self.inner().current_position,
463 relative_motion,
464 Some(tracing_id),
465 )];
466
467 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
468
469 _ = injector.inject_events(events_to_send).send_immediately();
470
471 Ok(())
472 } else {
473 Err(anyhow::format_err!(
474 "No injector found for mouse device {}.",
475 mouse_descriptor.device_id
476 ))
477 }
478 }
479
480 fn create_pointer_sample_event(
489 &self,
490 mouse_event: &mouse_binding::MouseEvent,
491 event_time: zx::MonotonicInstant,
492 phase: pointerinjector::EventPhase,
493 current_position: Position,
494 relative_motion: Option<[f32; 2]>,
495 trace_id: Option<u64>,
496 ) -> pointerinjector::Event {
497 let pointer_sample = pointerinjector::PointerSample {
498 pointer_id: Some(0),
499 phase: Some(phase),
500 position_in_viewport: Some([current_position.x, current_position.y]),
501 scroll_v: mouse_event.wheel_delta_v.as_ref().map(|delta| delta.ticks),
502 scroll_h: mouse_event.wheel_delta_h.as_ref().map(|delta| delta.ticks),
503 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
504 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
505 Some(pixel.into())
506 }
507 _ => None,
508 },
509 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
510 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
511 Some(pixel.into())
512 }
513 _ => None,
514 },
515 is_precision_scroll: match mouse_event.phase {
516 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
517 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
518 Some(mouse_binding::PrecisionScroll::No) => Some(false),
519 None => {
520 self.metrics_logger.log_error(
521 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
522 "mouse wheel event does not have value in is_precision_scroll.");
523 None
524 }
525 },
526 _ => None,
527 },
528 pressed_buttons: Some(mouse_event.pressed_buttons.clone().into()),
529 relative_motion,
530 ..Default::default()
531 };
532 pointerinjector::Event {
533 timestamp: Some(event_time.into_nanos()),
534 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
535 trace_flow_id: trace_id,
536 wake_lease: mouse_event.wake_lease.lock().take(),
537 ..Default::default()
538 }
539 }
540
541 pub async fn watch_viewport(self: Rc<Self>) {
543 let configuration_proxy = self.configuration_proxy.clone();
544 let mut viewport_stream = HangingGetStream::new(
545 configuration_proxy,
546 pointerinjector_config::SetupProxy::watch_viewport,
547 );
548 loop {
549 match viewport_stream.next().await {
550 Some(Ok(new_viewport)) => {
551 self.inner_mut().viewport = Some(utils::viewport_to_next(&new_viewport));
553
554 let injectors =
556 self.inner().injectors.iter().map(|(_, v)| v).cloned().collect::<Vec<_>>();
557 for injector in injectors {
558 let events = vec![pointerinjector::Event {
559 timestamp: Some(MonotonicInstant::now().into_nanos()),
560 data: Some(pointerinjector::Data::Viewport(utils::viewport_to_next(
561 &new_viewport,
562 ))),
563 trace_flow_id: Some(fuchsia_trace::Id::new().into()),
564 ..Default::default()
565 }];
566 injector
567 .inject_events(events)
568 .await
569 .expect("Failed to inject updated viewport.");
570 }
571 }
572 Some(Err(e)) => {
573 self.metrics_logger.log_error(
574 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
575 std::format!("Error while reading viewport update: {}", e));
576 return;
577 }
578 None => {
579 self.metrics_logger.log_error(
580 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
581 "Viewport update stream terminated unexpectedly");
582 return;
583 }
584 }
585 }
586 }
587}
588
589#[cfg(test)]
590mod tests {
591 use super::*;
592 use crate::testing_utilities::{
593 assert_handler_ignores_input_event_sequence, create_mouse_event,
594 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
595 create_mouse_pointer_sample_event_phase_add,
596 create_mouse_pointer_sample_event_with_wheel_physical_pixel, next_client_old_stream,
597 };
598 use assert_matches::assert_matches;
599 use fidl_fuchsia_input_report as fidl_input_report;
600 use fidl_fuchsia_ui_pointerinjector as pointerinjector;
601 use fidl_next_fuchsia_ui_pointerinjector as pointerinjector_next;
602 use fuchsia_async as fasync;
603 use futures::channel::mpsc;
604 use pretty_assertions::assert_eq;
605 use sorted_vec_map::SortedVecSet;
606 use std::ops::Add;
607 use test_case::test_case;
608
609 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
610 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
611 const DESCRIPTOR: input_device::InputDeviceDescriptor =
613 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
614 device_id: 1,
615 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
616 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
617 wheel_v_range: Some(fidl_input_report::Axis {
618 range: fidl_input_report::Range { min: -1, max: 1 },
619 unit: fidl_input_report::Unit {
620 type_: fidl_input_report::UnitType::Other,
621 exponent: 0,
622 },
623 }),
624 wheel_h_range: Some(fidl_input_report::Axis {
625 range: fidl_input_report::Range { min: -1, max: 1 },
626 unit: fidl_input_report::Unit {
627 type_: fidl_input_report::UnitType::Other,
628 exponent: 0,
629 },
630 }),
631 buttons: None,
632 });
633
634 async fn handle_configuration_request_stream(
636 stream: &mut pointerinjector_config::SetupRequestStream,
637 ) {
638 if let Some(Ok(request)) = stream.next().await {
639 match request {
640 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
641 let context = fuchsia_scenic::ViewRefPair::new()
642 .expect("Failed to create viewrefpair.")
643 .view_ref;
644 let target = fuchsia_scenic::ViewRefPair::new()
645 .expect("Failed to create viewrefpair.")
646 .view_ref;
647 let _ = responder.send(context, target);
648 }
649 _ => {}
650 };
651 }
652 }
653
654 async fn handle_registry_request_stream(
657 mut stream: pointerinjector::RegistryRequestStream,
658 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
659 ) {
660 if let Some(request) = stream.next().await {
661 match request {
662 Ok(pointerinjector::RegistryRequest::Register {
663 config: _,
664 injector,
665 responder,
666 ..
667 }) => {
668 let injector_stream = injector.into_stream();
669 let _ = injector_sender.send(injector_stream);
670 responder.send().expect("failed to respond");
671 }
672 _ => {}
673 };
674 } else {
675 panic!("RegistryRequestStream failed.");
676 }
677 }
678
679 async fn handle_registry_request_stream2(
681 mut stream: pointerinjector::RegistryRequestStream,
682 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
683 ) {
684 let (injector, responder) = match stream.next().await {
685 Some(Ok(pointerinjector::RegistryRequest::Register {
686 config: _,
687 injector,
688 responder,
689 ..
690 })) => (injector, responder),
691 other => panic!("expected register request, but got {:?}", other),
692 };
693 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
694 responder.send().expect("failed to respond");
695 injector_stream
696 .for_each(|request| {
697 futures::future::ready({
698 match request {
699 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
700 panic!("DeviceRequest::Inject is deprecated.");
701 }
702 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
703 let _ = injector_sender.unbounded_send(events);
704 }
705 Err(e) => panic!("FIDL error {}", e),
706 }
707 })
708 })
709 .await;
710 }
711
712 async fn handle_device_request_stream(
715 injector_stream_receiver: futures::channel::oneshot::Receiver<
716 pointerinjector::DeviceRequestStream,
717 >,
718 expected_events: Vec<pointerinjector::Event>,
719 ) {
720 let mut injector_stream =
721 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
722 for expected_event in expected_events {
723 match injector_stream.next().await {
724 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
725 panic!("DeviceRequest::Inject is deprecated.");
726 }
727 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
728 assert_eq!(events, vec![expected_event]);
729 }
730 Some(Err(e)) => panic!("FIDL error {}", e),
731 None => panic!("Expected another event."),
732 }
733 }
734 }
735
736 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
738 pointerinjector::Viewport {
739 extents: Some([[min, min], [max, max]]),
740 viewport_to_context_transform: None,
741 ..Default::default()
742 }
743 }
744
745 fn create_viewport_next(min: f32, max: f32) -> pointerinjector_next::Viewport {
746 pointerinjector_next::Viewport {
747 extents: Some([[min, min], [max, max]]),
748 viewport_to_context_transform: None,
749 ..Default::default()
750 }
751 }
752
753 #[fuchsia::test]
756 fn receives_viewport_updates() {
757 let mut exec = fasync::TestExecutor::new();
758
759 let (configuration_proxy, mut configuration_request_stream) =
761 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
762 let (injector_registry_proxy, _) =
763 fidl_next::fuchsia::create_channel::<pointerinjector_next::Registry>();
764 let injector_registry_proxy =
765 Dispatcher::client_from_zx_channel(injector_registry_proxy).spawn();
766 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
767
768 let inspector = fuchsia_inspect::Inspector::default();
769 let test_node = inspector.root().create_child("test_node");
770
771 let mouse_handler_fut = MouseInjectorHandler::new_handler(
773 configuration_proxy,
774 injector_registry_proxy,
775 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
776 sender,
777 &test_node,
778 metrics::MetricsLogger::default(),
779 );
780 let config_request_stream_fut =
781 handle_configuration_request_stream(&mut configuration_request_stream);
782 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
783 mouse_handler_fut,
784 config_request_stream_fut,
785 ));
786 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
787
788 let (injector_device_proxy, mut injector_device_request_stream) =
790 next_client_old_stream::<pointerinjector::DeviceMarker, pointerinjector_next::Device>();
791 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
792
793 {
795 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
797 futures::pin_mut!(watch_viewport_fut);
798 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
799
800 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
802 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
803 responder, ..
804 })) => {
805 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
806 }
807 other => panic!("Received unexpected value: {:?}", other),
808 };
809 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
810
811 exec.run_singlethreaded(async {
813 match injector_device_request_stream.next().await {
814 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
815 panic!("DeviceRequest::Inject is deprecated.");
816 }
817 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
818 assert_eq!(events.len(), 1);
819 assert!(events[0].data.is_some());
820 assert_eq!(
821 events[0].data,
822 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
823 );
824 }
825 other => panic!("Received unexpected value: {:?}", other),
826 }
827 });
828
829 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
831
832 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
834 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
835 responder, ..
836 })) => {
837 responder
838 .send(&create_viewport(100.0, 200.0))
839 .expect("Failed to send viewport.");
840 }
841 other => panic!("Received unexpected value: {:?}", other),
842 };
843
844 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
846 }
847
848 exec.run_singlethreaded(async {
850 match injector_device_request_stream.next().await {
851 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
852 panic!("DeviceRequest::Inject is deprecated.");
853 }
854 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
855 assert_eq!(events.len(), 1);
856 assert!(events[0].data.is_some());
857 assert_eq!(
858 events[0].data,
859 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
860 );
861 }
862 other => panic!("Received unexpected value: {:?}", other),
863 }
864 });
865
866 let expected_viewport = create_viewport_next(100.0, 200.0);
868 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
869 }
870
871 fn wheel_delta_ticks(
872 ticks: i64,
873 physical_pixel: Option<f32>,
874 ) -> Option<mouse_binding::WheelDelta> {
875 Some(mouse_binding::WheelDelta { ticks, physical_pixel })
876 }
877
878 #[test_case(
881 mouse_binding::MouseLocation::Relative(
882 mouse_binding::RelativeLocation {
883 counts: Position { x: 10.0, y: 20.0 }
884 }),
885 Position {
886 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0 + 10.0,
887 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0 + 20.0,
888 },
889 [10.0, 20.0]; "Valid move event."
890 )]
891 #[test_case(
892 mouse_binding::MouseLocation::Relative(
893 mouse_binding::RelativeLocation {
894 counts: Position {
895 x: DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0,
896 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0,
897 }}),
898 Position {
899 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
900 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
901 },
902 [
903 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0,
904 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0,
905 ]; "Move event exceeds max bounds."
906 )]
907 #[test_case(
908 mouse_binding::MouseLocation::Relative(
909 mouse_binding::RelativeLocation {
910 counts: Position {
911 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0),
912 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0),
913 }}),
914 Position { x: 0.0, y: 0.0 },
915 [
916 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0),
917 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0),
918 ]; "Move event exceeds min bounds."
919 )]
920 #[fuchsia::test(allow_stalls = false)]
921 async fn move_event(
922 move_location: mouse_binding::MouseLocation,
923 expected_position: Position,
924 expected_relative_motion: [f32; 2],
925 ) {
926 let (configuration_proxy, mut configuration_request_stream) =
928 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
929 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
930 pointerinjector::RegistryMarker,
931 pointerinjector_next::Registry,
932 >();
933 let config_request_stream_fut =
934 handle_configuration_request_stream(&mut configuration_request_stream);
935
936 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
938 let inspector = fuchsia_inspect::Inspector::default();
939 let test_node = inspector.root().create_child("test_node");
940 let mouse_handler_fut = MouseInjectorHandler::new_handler(
941 configuration_proxy,
942 injector_registry_proxy,
943 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
944 sender,
945 &test_node,
946 metrics::MetricsLogger::default(),
947 );
948 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
949 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
950
951 let event_time = zx::MonotonicInstant::get();
952 let input_event = create_mouse_event(
953 move_location,
954 None, None, None, mouse_binding::MousePhase::Move,
958 SortedVecSet::new(),
959 SortedVecSet::new(),
960 event_time,
961 &DESCRIPTOR,
962 );
963
964 let handle_event_fut = mouse_handler.handle_input_event(input_event);
966 let expected_events = vec![
967 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
968 create_mouse_pointer_sample_event(
969 pointerinjector::EventPhase::Change,
970 vec![],
971 expected_position,
972 Some(expected_relative_motion),
973 None, None, None, event_time,
977 ),
978 ];
979
980 let (injector_stream_sender, injector_stream_receiver) =
984 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
985 let registry_fut = handle_registry_request_stream(
986 injector_registry_request_stream,
987 injector_stream_sender,
988 );
989 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
990
991 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
994 match receiver.next().await {
995 Some(CursorMessage::SetPosition(position)) => {
996 pretty_assertions::assert_eq!(position, expected_position);
997 }
998 Some(CursorMessage::SetVisibility(_)) => {
999 panic!("Received unexpected cursor visibility update.")
1000 }
1001 None => panic!("Did not receive cursor update."),
1002 }
1003
1004 assert_matches!(
1006 handle_result.as_slice(),
1007 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1008 );
1009 }
1010
1011 #[fuchsia::test(allow_stalls = false)]
1014 async fn move_absolute_event() {
1015 const DEVICE_ID: u32 = 1;
1016
1017 let (configuration_proxy, mut configuration_request_stream) =
1019 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1020 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1021 pointerinjector::RegistryMarker,
1022 pointerinjector_next::Registry,
1023 >();
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 });
1069 let input_event = create_mouse_event(
1070 cursor_location,
1071 None, None, None, mouse_binding::MousePhase::Move,
1075 SortedVecSet::new(),
1076 SortedVecSet::new(),
1077 event_time,
1078 &descriptor,
1079 );
1080
1081 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1083 let expected_position = Position {
1084 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1085 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1086 };
1087 let expected_events = vec![
1088 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1089 create_mouse_pointer_sample_event(
1090 pointerinjector::EventPhase::Change,
1091 vec![],
1092 expected_position,
1093 None, None, None, None, event_time,
1098 ),
1099 ];
1100
1101 let (injector_stream_sender, injector_stream_receiver) =
1105 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1106 let registry_fut = handle_registry_request_stream(
1107 injector_registry_request_stream,
1108 injector_stream_sender,
1109 );
1110 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1111
1112 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1115 match receiver.next().await {
1116 Some(CursorMessage::SetPosition(position)) => {
1117 assert_eq!(position, expected_position);
1118 }
1119 Some(CursorMessage::SetVisibility(_)) => {
1120 panic!("Received unexpected cursor visibility update.")
1121 }
1122 None => panic!("Did not receive cursor update."),
1123 }
1124
1125 assert_matches!(
1127 handle_result.as_slice(),
1128 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1129 );
1130 }
1131
1132 #[test_case(
1134 mouse_binding::MousePhase::Down,
1135 vec![1], vec![1]; "Down event injects button press state."
1136 )]
1137 #[test_case(
1138 mouse_binding::MousePhase::Up,
1139 vec![1], vec![]; "Up event injects button press state."
1140 )]
1141 #[fuchsia::test(allow_stalls = false)]
1142 async fn button_state_event(
1143 phase: mouse_binding::MousePhase,
1144 affected_buttons: Vec<mouse_binding::MouseButton>,
1145 pressed_buttons: Vec<mouse_binding::MouseButton>,
1146 ) {
1147 let (configuration_proxy, mut configuration_request_stream) =
1149 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1150 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1151 pointerinjector::RegistryMarker,
1152 pointerinjector_next::Registry,
1153 >();
1154 let config_request_stream_fut =
1155 handle_configuration_request_stream(&mut configuration_request_stream);
1156
1157 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1159 let inspector = fuchsia_inspect::Inspector::default();
1160 let test_node = inspector.root().create_child("test_node");
1161 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1162 configuration_proxy,
1163 injector_registry_proxy,
1164 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1165 sender,
1166 &test_node,
1167 metrics::MetricsLogger::default(),
1168 );
1169 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1170 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1171
1172 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1173 let event_time = zx::MonotonicInstant::get();
1174
1175 let input_event = create_mouse_event(
1176 cursor_location,
1177 None, None, None, phase,
1181 affected_buttons.clone().into(),
1182 pressed_buttons.clone().into(),
1183 event_time,
1184 &DESCRIPTOR,
1185 );
1186
1187 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1189 let expected_position = Position { x: 0.0, y: 0.0 };
1190 let expected_events = vec![
1191 create_mouse_pointer_sample_event_phase_add(
1192 pressed_buttons.clone().into(),
1193 expected_position,
1194 event_time,
1195 ),
1196 create_mouse_pointer_sample_event(
1197 pointerinjector::EventPhase::Change,
1198 pressed_buttons.clone().into(),
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) = next_client_old_stream::<
1246 pointerinjector::RegistryMarker,
1247 pointerinjector_next::Registry,
1248 >();
1249 let config_request_stream_fut =
1250 handle_configuration_request_stream(&mut configuration_request_stream);
1251
1252 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1256 let inspector = fuchsia_inspect::Inspector::default();
1257 let test_node = inspector.root().create_child("test_node");
1258 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1259 configuration_proxy,
1260 injector_registry_proxy,
1261 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1262 sender,
1263 &test_node,
1264 metrics::MetricsLogger::default(),
1265 );
1266 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1267 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1268
1269 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1270 let event_time1 = zx::MonotonicInstant::get();
1271 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1272
1273 let event1 = create_mouse_event(
1274 cursor_location,
1275 None, None, None, mouse_binding::MousePhase::Down,
1279 SortedVecSet::from(vec![1]),
1280 SortedVecSet::from(vec![1]),
1281 event_time1,
1282 &DESCRIPTOR,
1283 );
1284
1285 let event2 = create_mouse_event(
1286 cursor_location,
1287 None, None, None, mouse_binding::MousePhase::Up,
1291 SortedVecSet::from(vec![1]),
1292 SortedVecSet::new(),
1293 event_time2,
1294 &DESCRIPTOR,
1295 );
1296
1297 let expected_position = Position { x: 0.0, y: 0.0 };
1298
1299 let (injector_stream_sender, injector_stream_receiver) =
1303 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1304 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1306 let registry_fut = handle_registry_request_stream2(
1307 injector_registry_request_stream,
1308 injector_stream_sender,
1309 );
1310
1311 let _registry_task = fasync::Task::local(registry_fut);
1313
1314 mouse_handler.clone().handle_input_event(event1).await;
1315 assert_eq!(
1316 injector_stream_receiver
1317 .next()
1318 .await
1319 .map(|events| events.into_iter().flatten().collect()),
1320 Some(vec![
1321 create_mouse_pointer_sample_event_phase_add(
1322 vec![1],
1323 expected_position,
1324 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
1343 .next()
1344 .await
1345 .map(|events| events.into_iter().flatten().collect()),
1346 Some(vec![create_mouse_pointer_sample_event(
1347 pointerinjector::EventPhase::Change,
1348 vec![],
1349 expected_position,
1350 None, None, None, None, event_time2,
1355 )])
1356 );
1357
1358 match receiver.next().await {
1360 Some(CursorMessage::SetPosition(position)) => {
1361 assert_eq!(position, expected_position);
1362 }
1363 Some(CursorMessage::SetVisibility(_)) => {
1364 panic!("Received unexpected cursor visibility update.")
1365 }
1366 None => panic!("Did not receive cursor update."),
1367 }
1368 }
1369
1370 #[fuchsia::test(allow_stalls = false)]
1380 async fn down_down_up_up_event() {
1381 let (configuration_proxy, mut configuration_request_stream) =
1383 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1384 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1385 pointerinjector::RegistryMarker,
1386 pointerinjector_next::Registry,
1387 >();
1388 let config_request_stream_fut =
1389 handle_configuration_request_stream(&mut configuration_request_stream);
1390
1391 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1395 let inspector = fuchsia_inspect::Inspector::default();
1396 let test_node = inspector.root().create_child("test_node");
1397 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1398 configuration_proxy,
1399 injector_registry_proxy,
1400 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1401 sender,
1402 &test_node,
1403 metrics::MetricsLogger::default(),
1404 );
1405 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1406 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1407
1408 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1409 let event_time1 = zx::MonotonicInstant::get();
1410 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1411 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1412 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1413
1414 let event1 = create_mouse_event(
1415 cursor_location,
1416 None, None, None, mouse_binding::MousePhase::Down,
1420 SortedVecSet::from(vec![1]),
1421 SortedVecSet::from(vec![1]),
1422 event_time1,
1423 &DESCRIPTOR,
1424 );
1425 let event2 = create_mouse_event(
1426 cursor_location,
1427 None, None, None, mouse_binding::MousePhase::Down,
1431 SortedVecSet::from(vec![2]),
1432 SortedVecSet::from(vec![1, 2]),
1433 event_time2,
1434 &DESCRIPTOR,
1435 );
1436 let event3 = create_mouse_event(
1437 cursor_location,
1438 None, None, None, mouse_binding::MousePhase::Up,
1442 SortedVecSet::from(vec![1]),
1443 SortedVecSet::from(vec![2]),
1444 event_time3,
1445 &DESCRIPTOR,
1446 );
1447 let event4 = create_mouse_event(
1448 cursor_location,
1449 None, None, None, mouse_binding::MousePhase::Up,
1453 SortedVecSet::from(vec![2]),
1454 SortedVecSet::new(),
1455 event_time4,
1456 &DESCRIPTOR,
1457 );
1458
1459 let expected_position = Position { x: 0.0, y: 0.0 };
1460
1461 let (injector_stream_sender, injector_stream_receiver) =
1465 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1466 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1468 let registry_fut = handle_registry_request_stream2(
1469 injector_registry_request_stream,
1470 injector_stream_sender,
1471 );
1472
1473 let _registry_task = fasync::Task::local(registry_fut);
1475 mouse_handler.clone().handle_input_event(event1).await;
1476 assert_eq!(
1477 injector_stream_receiver
1478 .next()
1479 .await
1480 .map(|events| events.into_iter().flatten().collect()),
1481 Some(vec![
1482 create_mouse_pointer_sample_event_phase_add(
1483 vec![1],
1484 expected_position,
1485 event_time1,
1486 ),
1487 create_mouse_pointer_sample_event(
1488 pointerinjector::EventPhase::Change,
1489 vec![1],
1490 expected_position,
1491 None, None, None, None, event_time1,
1496 )
1497 ])
1498 );
1499
1500 mouse_handler.clone().handle_input_event(event2).await;
1502 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1503 .next()
1504 .await
1505 .map(|events| events.into_iter().flatten().collect())
1506 .expect("Failed to receive pointer sample event.");
1507 let expected_event_time: i64 = event_time2.into_nanos();
1508 assert_eq!(pointer_sample_event2.len(), 1);
1509
1510 match &pointer_sample_event2[0] {
1513 pointerinjector::Event {
1514 timestamp: Some(actual_event_time),
1515 data:
1516 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1517 pointer_id: Some(0),
1518 phase: Some(pointerinjector::EventPhase::Change),
1519 position_in_viewport: Some(actual_position),
1520 scroll_v: None,
1521 scroll_h: None,
1522 pressed_buttons: Some(actual_buttons),
1523 relative_motion: None,
1524 ..
1525 })),
1526 ..
1527 } => {
1528 assert_eq!(*actual_event_time, expected_event_time);
1529 assert_eq!(actual_position[0], expected_position.x);
1530 assert_eq!(actual_position[1], expected_position.y);
1531 assert_eq!(actual_buttons.as_slice(), &[1u8, 2u8]);
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
1540 .next()
1541 .await
1542 .map(|events| events.into_iter().flatten().collect()),
1543 Some(vec![create_mouse_pointer_sample_event(
1544 pointerinjector::EventPhase::Change,
1545 vec![2],
1546 expected_position,
1547 None, None, None, None, event_time3,
1552 )])
1553 );
1554
1555 mouse_handler.clone().handle_input_event(event4).await;
1557 assert_eq!(
1558 injector_stream_receiver
1559 .next()
1560 .await
1561 .map(|events| events.into_iter().flatten().collect()),
1562 Some(vec![create_mouse_pointer_sample_event(
1563 pointerinjector::EventPhase::Change,
1564 vec![],
1565 expected_position,
1566 None, None, None, None, event_time4,
1571 )])
1572 );
1573
1574 match receiver.next().await {
1576 Some(CursorMessage::SetPosition(position)) => {
1577 assert_eq!(position, expected_position);
1578 }
1579 Some(CursorMessage::SetVisibility(_)) => {
1580 panic!("Received unexpected cursor visibility update.")
1581 }
1582 None => panic!("Did not receive cursor update."),
1583 }
1584 }
1585
1586 #[fuchsia::test(allow_stalls = false)]
1588 async fn down_move_up_event() {
1589 let (configuration_proxy, mut configuration_request_stream) =
1591 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1592 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1593 pointerinjector::RegistryMarker,
1594 pointerinjector_next::Registry,
1595 >();
1596 let config_request_stream_fut =
1597 handle_configuration_request_stream(&mut configuration_request_stream);
1598
1599 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1603 let inspector = fuchsia_inspect::Inspector::default();
1604 let test_node = inspector.root().create_child("test_node");
1605 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1606 configuration_proxy,
1607 injector_registry_proxy,
1608 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1609 sender,
1610 &test_node,
1611 metrics::MetricsLogger::default(),
1612 );
1613 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1614 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1615
1616 let event_time1 = zx::MonotonicInstant::get();
1617 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1618 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1619 let zero_position = Position { x: 0.0, y: 0.0 };
1620 let expected_position = Position { x: 10.0, y: 5.0 };
1621 let expected_relative_motion = [10.0, 5.0];
1622 let event1 = create_mouse_event(
1623 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1624 None, None, None, mouse_binding::MousePhase::Down,
1628 SortedVecSet::from(vec![1]),
1629 SortedVecSet::from(vec![1]),
1630 event_time1,
1631 &DESCRIPTOR,
1632 );
1633 let event2 = create_mouse_event(
1634 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1635 counts: Position { x: 10.0, y: 5.0 },
1636 }),
1637 None, None, None, mouse_binding::MousePhase::Move,
1641 SortedVecSet::from(vec![1]),
1642 SortedVecSet::from(vec![1]),
1643 event_time2,
1644 &DESCRIPTOR,
1645 );
1646 let event3 = create_mouse_event(
1647 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1648 counts: Position { x: 0.0, y: 0.0 },
1649 }),
1650 None, None, None, mouse_binding::MousePhase::Up,
1654 SortedVecSet::from(vec![1]),
1655 SortedVecSet::new(),
1656 event_time3,
1657 &DESCRIPTOR,
1658 );
1659
1660 let (injector_stream_sender, injector_stream_receiver) =
1664 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1665 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1667 let registry_fut = handle_registry_request_stream2(
1668 injector_registry_request_stream,
1669 injector_stream_sender,
1670 );
1671
1672 let _registry_task = fasync::Task::local(registry_fut);
1674 mouse_handler.clone().handle_input_event(event1).await;
1675 assert_eq!(
1676 injector_stream_receiver
1677 .next()
1678 .await
1679 .map(|events| events.into_iter().flatten().collect()),
1680 Some(vec![
1681 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1682 create_mouse_pointer_sample_event(
1683 pointerinjector::EventPhase::Change,
1684 vec![1],
1685 zero_position,
1686 None, None, None, None, event_time1,
1691 )
1692 ])
1693 );
1694
1695 match receiver.next().await {
1697 Some(CursorMessage::SetPosition(position)) => {
1698 assert_eq!(position, zero_position);
1699 }
1700 Some(CursorMessage::SetVisibility(_)) => {
1701 panic!("Received unexpected cursor visibility update.")
1702 }
1703 None => panic!("Did not receive cursor update."),
1704 }
1705
1706 mouse_handler.clone().handle_input_event(event2).await;
1708 assert_eq!(
1709 injector_stream_receiver
1710 .next()
1711 .await
1712 .map(|events| events.into_iter().flatten().collect()),
1713 Some(vec![create_mouse_pointer_sample_event(
1714 pointerinjector::EventPhase::Change,
1715 vec![1],
1716 expected_position,
1717 Some(expected_relative_motion),
1718 None, None, None, event_time2,
1722 )])
1723 );
1724
1725 match receiver.next().await {
1727 Some(CursorMessage::SetPosition(position)) => {
1728 assert_eq!(position, expected_position);
1729 }
1730 Some(CursorMessage::SetVisibility(_)) => {
1731 panic!("Received unexpected cursor visibility update.")
1732 }
1733 None => panic!("Did not receive cursor update."),
1734 }
1735
1736 mouse_handler.clone().handle_input_event(event3).await;
1738 assert_eq!(
1739 injector_stream_receiver
1740 .next()
1741 .await
1742 .map(|events| events.into_iter().flatten().collect()),
1743 Some(vec![create_mouse_pointer_sample_event(
1744 pointerinjector::EventPhase::Change,
1745 vec![],
1746 expected_position,
1747 None, None, None, None, event_time3,
1752 )])
1753 );
1754
1755 match receiver.next().await {
1757 Some(CursorMessage::SetPosition(position)) => {
1758 assert_eq!(position, expected_position);
1759 }
1760 Some(CursorMessage::SetVisibility(_)) => {
1761 panic!("Received unexpected cursor visibility update.")
1762 }
1763 None => panic!("Did not receive cursor update."),
1764 }
1765 }
1766
1767 #[fuchsia::test(allow_stalls = false)]
1769 async fn handler_ignores_handled_events() {
1770 let (configuration_proxy, mut configuration_request_stream) =
1772 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1773 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1774 pointerinjector::RegistryMarker,
1775 pointerinjector_next::Registry,
1776 >();
1777 let config_request_stream_fut =
1778 handle_configuration_request_stream(&mut configuration_request_stream);
1779
1780 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1782 let inspector = fuchsia_inspect::Inspector::default();
1783 let test_node = inspector.root().create_child("test_node");
1784 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1785 configuration_proxy,
1786 injector_registry_proxy,
1787 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1788 sender,
1789 &test_node,
1790 metrics::MetricsLogger::default(),
1791 );
1792 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1793 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1794
1795 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1796 let cursor_location =
1797 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1798 counts: Position { x: cursor_relative_position.x, y: cursor_relative_position.y },
1799 });
1800 let event_time = zx::MonotonicInstant::get();
1801 let input_events = vec![create_mouse_event_with_handled(
1802 cursor_location,
1803 None, None, None, mouse_binding::MousePhase::Move,
1807 SortedVecSet::new(),
1808 SortedVecSet::new(),
1809 event_time,
1810 &DESCRIPTOR,
1811 input_device::Handled::Yes,
1812 )];
1813
1814 assert_handler_ignores_input_event_sequence(
1815 mouse_handler,
1816 input_events,
1817 injector_registry_request_stream,
1818 )
1819 .await;
1820
1821 assert!(receiver.next().await.is_none());
1823 }
1824
1825 fn zero_relative_location() -> mouse_binding::MouseLocation {
1826 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1827 counts: Position { x: 0.0, y: 0.0 },
1828 })
1829 }
1830
1831 #[test_case(
1832 create_mouse_event(
1833 zero_relative_location(),
1834 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1838 SortedVecSet::new(),
1839 SortedVecSet::new(),
1840 zx::MonotonicInstant::ZERO,
1841 &DESCRIPTOR,
1842 ),
1843 create_mouse_pointer_sample_event(
1844 pointerinjector::EventPhase::Change,
1845 vec![],
1846 Position { x: 50.0, y: 50.0 },
1847 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1852 ); "v tick scroll"
1853 )]
1854 #[test_case(
1855 create_mouse_event(
1856 zero_relative_location(),
1857 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1861 SortedVecSet::new(),
1862 SortedVecSet::new(),
1863 zx::MonotonicInstant::ZERO,
1864 &DESCRIPTOR,
1865 ),
1866 create_mouse_pointer_sample_event(
1867 pointerinjector::EventPhase::Change,
1868 vec![],
1869 Position { x: 50.0, y: 50.0 },
1870 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1875 ); "h tick scroll"
1876 )]
1877 #[test_case(
1878 create_mouse_event(
1879 zero_relative_location(),
1880 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1884 SortedVecSet::new(),
1885 SortedVecSet::new(),
1886 zx::MonotonicInstant::ZERO,
1887 &DESCRIPTOR,
1888 ),
1889 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1890 pointerinjector::EventPhase::Change,
1891 vec![],
1892 Position { x: 50.0, y: 50.0 },
1893 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1900 ); "v tick scroll with physical pixel"
1901 )]
1902 #[test_case(
1903 create_mouse_event(
1904 zero_relative_location(),
1905 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1909 SortedVecSet::new(),
1910 SortedVecSet::new(),
1911 zx::MonotonicInstant::ZERO,
1912 &DESCRIPTOR,
1913 ),
1914 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1915 pointerinjector::EventPhase::Change,
1916 vec![],
1917 Position { x: 50.0, y: 50.0 },
1918 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1925 ); "h tick scroll with physical pixel"
1926 )]
1927 #[test_case(
1928 create_mouse_event(
1929 zero_relative_location(),
1930 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1934 SortedVecSet::new(),
1935 SortedVecSet::new(),
1936 zx::MonotonicInstant::ZERO,
1937 &DESCRIPTOR,
1938 ),
1939 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1940 pointerinjector::EventPhase::Change,
1941 vec![],
1942 Position { x: 50.0, y: 50.0 },
1943 None, Some(1), None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1950 ); "v precision scroll with physical pixel"
1951 )]
1952 #[test_case(
1953 create_mouse_event(
1954 zero_relative_location(),
1955 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1959 SortedVecSet::new(),
1960 SortedVecSet::new(),
1961 zx::MonotonicInstant::ZERO,
1962 &DESCRIPTOR,
1963 ),
1964 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1965 pointerinjector::EventPhase::Change,
1966 vec![],
1967 Position { x: 50.0, y: 50.0 },
1968 None, None, Some(1), None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1975 ); "h precision scroll with physical pixel"
1976 )]
1977 #[fuchsia::test(allow_stalls = false)]
1979 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1980 let (configuration_proxy, mut configuration_request_stream) =
1982 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1983 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1984 pointerinjector::RegistryMarker,
1985 pointerinjector_next::Registry,
1986 >();
1987 let config_request_stream_fut =
1988 handle_configuration_request_stream(&mut configuration_request_stream);
1989
1990 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1992 let inspector = fuchsia_inspect::Inspector::default();
1993 let test_node = inspector.root().create_child("test_node");
1994 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1995 configuration_proxy,
1996 injector_registry_proxy,
1997 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1998 sender,
1999 &test_node,
2000 metrics::MetricsLogger::default(),
2001 );
2002 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2003 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2004
2005 let (injector_stream_sender, injector_stream_receiver) =
2009 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2010 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2012 let registry_fut = handle_registry_request_stream2(
2013 injector_registry_request_stream,
2014 injector_stream_sender,
2015 );
2016
2017 let event_time = zx::MonotonicInstant::get();
2018
2019 let event = input_device::InputEvent { event_time, ..event };
2020
2021 let want_event =
2022 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2023
2024 let _registry_task = fasync::Task::local(registry_fut);
2026
2027 mouse_handler.clone().handle_input_event(event).await;
2028 let got_events: Vec<_> = injector_stream_receiver
2029 .next()
2030 .await
2031 .map(|events| events.into_iter().flatten().collect())
2032 .unwrap();
2033 pretty_assertions::assert_eq!(got_events.len(), 2);
2034 assert_matches!(
2035 got_events[0],
2036 pointerinjector::Event {
2037 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2038 phase: Some(pointerinjector::EventPhase::Add),
2039 ..
2040 })),
2041 ..
2042 }
2043 );
2044
2045 pretty_assertions::assert_eq!(got_events[1], want_event);
2046 }
2047
2048 #[fuchsia::test(allow_stalls = false)]
2050 async fn down_scroll_up_scroll() {
2051 let (configuration_proxy, mut configuration_request_stream) =
2053 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2054 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2055 pointerinjector::RegistryMarker,
2056 pointerinjector_next::Registry,
2057 >();
2058 let config_request_stream_fut =
2059 handle_configuration_request_stream(&mut configuration_request_stream);
2060
2061 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2063 let inspector = fuchsia_inspect::Inspector::default();
2064 let test_node = inspector.root().create_child("test_node");
2065 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2066 configuration_proxy,
2067 injector_registry_proxy,
2068 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2069 sender,
2070 &test_node,
2071 metrics::MetricsLogger::default(),
2072 );
2073 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2074 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2075
2076 let (injector_stream_sender, injector_stream_receiver) =
2080 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2081 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2083 let registry_fut = handle_registry_request_stream2(
2084 injector_registry_request_stream,
2085 injector_stream_sender,
2086 );
2087
2088 let event_time1 = zx::MonotonicInstant::get();
2089 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2090 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2091 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2092
2093 let _registry_task = fasync::Task::local(registry_fut);
2095
2096 let zero_location =
2097 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2098 counts: Position { x: 0.0, y: 0.0 },
2099 });
2100 let expected_position = Position { x: 50.0, y: 50.0 };
2101
2102 let down_event = create_mouse_event(
2103 zero_location,
2104 None, None, None, mouse_binding::MousePhase::Down,
2108 SortedVecSet::from(vec![1]),
2109 SortedVecSet::from(vec![1]),
2110 event_time1,
2111 &DESCRIPTOR,
2112 );
2113
2114 let wheel_event = create_mouse_event(
2115 zero_location,
2116 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2120 SortedVecSet::from(vec![1]),
2121 SortedVecSet::from(vec![1]),
2122 event_time2,
2123 &DESCRIPTOR,
2124 );
2125
2126 let up_event = create_mouse_event(
2127 zero_location,
2128 None,
2129 None,
2130 None, mouse_binding::MousePhase::Up,
2132 SortedVecSet::from(vec![1]),
2133 SortedVecSet::new(),
2134 event_time3,
2135 &DESCRIPTOR,
2136 );
2137
2138 let continue_wheel_event = create_mouse_event(
2139 zero_location,
2140 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2144 SortedVecSet::new(),
2145 SortedVecSet::new(),
2146 event_time4,
2147 &DESCRIPTOR,
2148 );
2149
2150 mouse_handler.clone().handle_input_event(down_event).await;
2152 assert_eq!(
2153 injector_stream_receiver
2154 .next()
2155 .await
2156 .map(|events| events.into_iter().flatten().collect()),
2157 Some(vec![
2158 create_mouse_pointer_sample_event_phase_add(
2159 vec![1],
2160 expected_position,
2161 event_time1,
2162 ),
2163 create_mouse_pointer_sample_event(
2164 pointerinjector::EventPhase::Change,
2165 vec![1],
2166 expected_position,
2167 None, None, None, None, event_time1,
2172 ),
2173 ])
2174 );
2175
2176 mouse_handler.clone().handle_input_event(wheel_event).await;
2178 assert_eq!(
2179 injector_stream_receiver
2180 .next()
2181 .await
2182 .map(|events| events.into_iter().flatten().collect()),
2183 Some(vec![create_mouse_pointer_sample_event(
2184 pointerinjector::EventPhase::Change,
2185 vec![1],
2186 expected_position,
2187 None, Some(1), None, Some(false), event_time2,
2192 )])
2193 );
2194
2195 mouse_handler.clone().handle_input_event(up_event).await;
2197 assert_eq!(
2198 injector_stream_receiver
2199 .next()
2200 .await
2201 .map(|events| events.into_iter().flatten().collect()),
2202 Some(vec![create_mouse_pointer_sample_event(
2203 pointerinjector::EventPhase::Change,
2204 vec![],
2205 expected_position,
2206 None, None, None, None, event_time3,
2211 )])
2212 );
2213
2214 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2216 assert_eq!(
2217 injector_stream_receiver
2218 .next()
2219 .await
2220 .map(|events| events.into_iter().flatten().collect()),
2221 Some(vec![create_mouse_pointer_sample_event(
2222 pointerinjector::EventPhase::Change,
2223 vec![],
2224 expected_position,
2225 None, Some(1), None, Some(false), event_time4,
2230 )])
2231 );
2232 }
2233
2234 #[fuchsia::test(allow_stalls = false)]
2235 async fn mouse_injector_handler_initialized_with_inspect_node() {
2236 let (configuration_proxy, mut configuration_request_stream) =
2237 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2238 let config_request_stream_fut =
2239 handle_configuration_request_stream(&mut configuration_request_stream);
2240 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2241 let inspector = fuchsia_inspect::Inspector::default();
2242 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2243 let incoming = Incoming::new();
2244 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2245 &incoming,
2246 configuration_proxy,
2247 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2248 sender,
2249 &fake_handlers_node,
2250 metrics::MetricsLogger::default(),
2251 );
2252 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2253 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2254
2255 diagnostics_assertions::assert_data_tree!(inspector, root: {
2256 input_handlers_node: {
2257 mouse_injector_handler: {
2258 events_received_count: 0u64,
2259 events_handled_count: 0u64,
2260 last_received_timestamp_ns: 0u64,
2261 "fuchsia.inspect.Health": {
2262 status: "STARTING_UP",
2263 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2266 },
2267 }
2268 }
2269 });
2270 }
2271
2272 #[fuchsia::test(allow_stalls = false)]
2273 async fn mouse_injector_handler_inspect_counts_events() {
2274 let (configuration_proxy, mut configuration_request_stream) =
2276 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2277 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2278 pointerinjector::RegistryMarker,
2279 pointerinjector_next::Registry,
2280 >();
2281 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2282
2283 let inspector = fuchsia_inspect::Inspector::default();
2284 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2285
2286 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2288 configuration_proxy,
2289 injector_registry_proxy,
2290 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2291 sender,
2292 &fake_handlers_node,
2293 metrics::MetricsLogger::default(),
2294 );
2295 let config_request_stream_fut =
2296 handle_configuration_request_stream(&mut configuration_request_stream);
2297
2298 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2299 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2300
2301 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2302 let event_time1 = zx::MonotonicInstant::get();
2303 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2304 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2305
2306 let input_events = vec![
2307 create_mouse_event(
2308 cursor_location,
2309 None, None, None, mouse_binding::MousePhase::Down,
2313 SortedVecSet::from(vec![1]),
2314 SortedVecSet::from(vec![1]),
2315 event_time1,
2316 &DESCRIPTOR,
2317 ),
2318 create_mouse_event(
2319 cursor_location,
2320 None, None, None, mouse_binding::MousePhase::Up,
2324 SortedVecSet::from(vec![1]),
2325 SortedVecSet::new(),
2326 event_time2,
2327 &DESCRIPTOR,
2328 ),
2329 create_mouse_event_with_handled(
2330 cursor_location,
2331 None, None, None, mouse_binding::MousePhase::Down,
2335 SortedVecSet::from(vec![1]),
2336 SortedVecSet::from(vec![1]),
2337 event_time3,
2338 &DESCRIPTOR,
2339 input_device::Handled::Yes,
2340 ),
2341 ];
2342
2343 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2347 let registry_fut = handle_registry_request_stream2(
2348 injector_registry_request_stream,
2349 injector_stream_sender,
2350 );
2351
2352 let _registry_task = fasync::Task::local(registry_fut);
2354 for input_event in input_events {
2355 mouse_handler.clone().handle_input_event(input_event).await;
2356 }
2357
2358 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2359
2360 diagnostics_assertions::assert_data_tree!(inspector, root: {
2361 input_handlers_node: {
2362 mouse_injector_handler: {
2363 events_received_count: 2u64,
2364 events_handled_count: 2u64,
2365 last_received_timestamp_ns: last_received_event_time,
2366 "fuchsia.inspect.Health": {
2367 status: "STARTING_UP",
2368 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2371 },
2372 }
2373 }
2374 });
2375 }
2376}