1use crate::display_ownership::DisplayOwnership;
6use crate::focus_listener::FocusListener;
7use crate::input_device::{InputEventType, InputPipelineFeatureFlags};
8use crate::input_handler::Handler;
9use crate::{Dispatcher, Incoming, Transport, dispatcher, input_device, input_handler, metrics};
10use anyhow::{Context, Error, format_err};
11use fidl::endpoints;
12use fidl_fuchsia_io as fio;
13use focus_chain_provider::FocusChainProviderPublisher;
14use fuchsia_async as fasync;
15use fuchsia_component::directory::AsRefDirectory;
16use fuchsia_fs::directory::{WatchEvent, Watcher};
17use fuchsia_inspect::NumericProperty;
18use fuchsia_inspect::health::Reporter;
19use fuchsia_sync::Mutex;
20use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
21use futures::future::LocalBoxFuture;
22use futures::{StreamExt, TryStreamExt};
23use itertools::Itertools;
24use metrics_registry::*;
25use sorted_vec_map::SortedVecMap;
26use std::path::Path;
27use std::rc::Rc;
28use std::sync::atomic::{AtomicU32, Ordering};
29use std::sync::{Arc, LazyLock};
30use strum::EnumCount;
31
32static NEXT_DEVICE_ID: LazyLock<AtomicU32> = LazyLock::new(|| AtomicU32::new(10));
39
40fn get_next_device_id() -> u32 {
44 NEXT_DEVICE_ID.fetch_add(1, Ordering::SeqCst)
45}
46
47type BoxedInputDeviceBinding = Box<dyn input_device::InputDeviceBinding>;
48
49pub type InputDeviceBindingMap = Arc<Mutex<SortedVecMap<u32, Vec<BoxedInputDeviceBinding>>>>;
52
53pub struct InputPipelineAssembly {
67 sender: UnboundedSender<Vec<input_device::InputEvent>>,
70 receiver: UnboundedReceiver<Vec<input_device::InputEvent>>,
73
74 handlers: Vec<Rc<dyn input_handler::BatchInputHandler>>,
76
77 display_ownership_fut: Option<LocalBoxFuture<'static, ()>>,
79
80 focus_listener_fut: Option<LocalBoxFuture<'static, ()>>,
82
83 metrics_logger: metrics::MetricsLogger,
85}
86
87impl InputPipelineAssembly {
88 pub fn new(metrics_logger: metrics::MetricsLogger) -> Self {
91 let (sender, receiver) = mpsc::unbounded();
92 InputPipelineAssembly {
93 sender,
94 receiver,
95 handlers: vec![],
96 metrics_logger,
97 display_ownership_fut: None,
98 focus_listener_fut: None,
99 }
100 }
101
102 pub fn add_handler(mut self, handler: Rc<dyn input_handler::BatchInputHandler>) -> Self {
105 self.handlers.push(handler);
106 self
107 }
108
109 pub fn add_all_handlers(self, handlers: Vec<Rc<dyn input_handler::BatchInputHandler>>) -> Self {
111 handlers.into_iter().fold(self, |assembly, handler| assembly.add_handler(handler))
112 }
113
114 pub fn add_display_ownership(
115 mut self,
116 display_ownership_event: zx::Event,
117 input_handlers_node: &fuchsia_inspect::Node,
118 ) -> InputPipelineAssembly {
119 let h = DisplayOwnership::new(
120 display_ownership_event,
121 input_handlers_node,
122 self.metrics_logger.clone(),
123 );
124 let metrics_logger_clone = self.metrics_logger.clone();
125 let h_clone = h.clone();
126 let sender_clone = self.sender.clone();
127 let display_ownership_fut = Box::pin(async move {
128 h_clone.clone().set_handler_healthy();
129 h_clone.clone()
130 .handle_ownership_change(sender_clone)
131 .await
132 .map_err(|e| {
133 metrics_logger_clone.log_error(
134 InputPipelineErrorMetricDimensionEvent::InputPipelineDisplayOwnershipIsNotSupposedToTerminate,
135 std::format!(
136 "display ownership is not supposed to terminate - this is likely a problem: {:?}", e));
137 })
138 .unwrap();
139 h_clone.set_handler_unhealthy("Receive loop terminated for handler: DisplayOwnership");
140 });
141 self.display_ownership_fut = Some(display_ownership_fut);
142 self.add_handler(h)
143 }
144
145 fn into_components(
151 self,
152 ) -> (
153 UnboundedSender<Vec<input_device::InputEvent>>,
154 UnboundedReceiver<Vec<input_device::InputEvent>>,
155 Vec<Rc<dyn input_handler::BatchInputHandler>>,
156 metrics::MetricsLogger,
157 Option<LocalBoxFuture<'static, ()>>,
158 Option<LocalBoxFuture<'static, ()>>,
159 ) {
160 (
161 self.sender,
162 self.receiver,
163 self.handlers,
164 self.metrics_logger,
165 self.display_ownership_fut,
166 self.focus_listener_fut,
167 )
168 }
169
170 pub fn add_focus_listener(
171 mut self,
172 incoming: &Incoming,
173 focus_chain_publisher: FocusChainProviderPublisher,
174 ) -> Self {
175 let metrics_logger_clone = self.metrics_logger.clone();
176 let incoming2 = incoming.clone();
177 let focus_listener_fut = Box::pin(async move {
178 if let Ok(mut focus_listener) = FocusListener::new(
179 &incoming2,
180 focus_chain_publisher,
181 metrics_logger_clone,
182 )
183 .map_err(|e| {
184 log::warn!("could not create focus listener, focus will not be dispatched: {:?}", e)
185 }) {
186 let _result = focus_listener
189 .dispatch_focus_changes()
190 .await
191 .map(|_| {
192 log::warn!("dispatch focus loop ended, focus will no longer be dispatched")
193 })
194 .map_err(|e| {
195 panic!("could not dispatch focus changes, this is a fatal error: {:?}", e)
196 });
197 }
198 });
199 self.focus_listener_fut = Some(focus_listener_fut);
200 self
201 }
202}
203
204pub struct InputPipeline {
232 pipeline_sender: UnboundedSender<Vec<input_device::InputEvent>>,
236
237 device_event_sender: UnboundedSender<Vec<input_device::InputEvent>>,
240
241 device_event_receiver: UnboundedReceiver<Vec<input_device::InputEvent>>,
243
244 input_device_types: Vec<input_device::InputDeviceType>,
246
247 input_device_bindings: InputDeviceBindingMap,
249
250 inspect_node: fuchsia_inspect::Node,
253
254 metrics_logger: metrics::MetricsLogger,
256
257 pub feature_flags: input_device::InputPipelineFeatureFlags,
259
260 _tasks: Vec<dispatcher::TaskHandle<()>>,
262
263 _fasync_tasks: Vec<fasync::Task<()>>,
265}
266
267impl InputPipeline {
268 fn new_common(
269 input_device_types: Vec<input_device::InputDeviceType>,
270 assembly: InputPipelineAssembly,
271 inspect_node: fuchsia_inspect::Node,
272 feature_flags: input_device::InputPipelineFeatureFlags,
273 ) -> Self {
274 let (
275 pipeline_sender,
276 receiver,
277 handlers,
278 metrics_logger,
279 display_ownership_fut,
280 focus_listener_fut,
281 ) = assembly.into_components();
282
283 let mut tasks = vec![];
284 let mut fasync_tasks = vec![];
285
286 let mut handlers_count = handlers.len();
287 if let Some(fut) = display_ownership_fut {
289 tasks.push(Dispatcher::spawn_local(fut));
293 handlers_count += 1;
294 }
295
296 if let Some(fut) = focus_listener_fut {
298 fasync_tasks.push(fasync::Task::local(fut));
299 handlers_count += 1;
300 }
301
302 inspect_node.record_string("supported_input_devices", input_device_types.iter().join(", "));
304 inspect_node.record_uint("handlers_registered", handlers_count as u64);
305 inspect_node.record_uint("handlers_healthy", handlers_count as u64);
306
307 let runner_task = InputPipeline::run(receiver, handlers, metrics_logger.clone());
309 tasks.push(runner_task);
310
311 let (device_event_sender, device_event_receiver) = futures::channel::mpsc::unbounded();
312 let input_device_bindings: InputDeviceBindingMap =
313 Arc::new(Mutex::new(SortedVecMap::new()));
314 InputPipeline {
315 pipeline_sender,
316 device_event_sender,
317 device_event_receiver,
318 input_device_types,
319 input_device_bindings,
320 inspect_node,
321 metrics_logger,
322 feature_flags,
323 _tasks: tasks,
324 _fasync_tasks: fasync_tasks,
325 }
326 }
327
328 pub fn new_for_test(
336 input_device_types: Vec<input_device::InputDeviceType>,
337 assembly: InputPipelineAssembly,
338 ) -> Self {
339 let inspector = fuchsia_inspect::Inspector::default();
340 let root = inspector.root();
341 let test_node = root.create_child("input_pipeline");
342 Self::new_common(
343 input_device_types,
344 assembly,
345 test_node,
346 input_device::InputPipelineFeatureFlags { enable_merge_touch_events: false },
347 )
348 }
349
350 pub fn new(
357 incoming: &Incoming,
358 input_device_types: Vec<input_device::InputDeviceType>,
359 assembly: InputPipelineAssembly,
360 inspect_node: fuchsia_inspect::Node,
361 feature_flags: input_device::InputPipelineFeatureFlags,
362 metrics_logger: metrics::MetricsLogger,
363 ) -> Result<Self, Error> {
364 let mut input_pipeline =
365 Self::new_common(input_device_types, assembly, inspect_node, feature_flags);
366 let input_device_types = input_pipeline.input_device_types.clone();
367 let input_event_sender = input_pipeline.device_event_sender.clone();
368 let input_device_bindings = input_pipeline.input_device_bindings.clone();
369 let devices_node = input_pipeline.inspect_node.create_child("input_devices");
370 let feature_flags = input_pipeline.feature_flags.clone();
371 let incoming = incoming.clone();
372 let watcher_task = fasync::Task::local(async move {
377 match async {
380 let (dir_proxy, server) = endpoints::create_proxy::<fio::DirectoryMarker>();
381 incoming
382 .as_ref_directory()
383 .open(input_device::INPUT_REPORT_PATH, fio::PERM_READABLE, server.into())
384 .with_context(|| {
385 format!("failed to open {}", input_device::INPUT_REPORT_PATH)
386 })?;
387 let device_watcher =
388 Watcher::new(&dir_proxy).await.context("failed to create watcher")?;
389 Self::watch_for_devices(
390 device_watcher,
391 dir_proxy,
392 &input_device_types,
393 input_event_sender,
394 input_device_bindings,
395 &devices_node,
396 false, feature_flags,
398 metrics_logger.clone(),
399 )
400 .await
401 .context("failed to watch for devices")
402 }
403 .await
404 {
405 Ok(()) => {}
406 Err(err) => {
407 metrics_logger.log_warn(
411 InputPipelineErrorMetricDimensionEvent::InputPipelineUnableToWatchForNewInputDevices,
412 std::format!(
413 "Input pipeline is unable to watch for new input devices: {:?}",
414 err
415 ));
416 }
417 }
418 });
419 input_pipeline._fasync_tasks.push(watcher_task);
420
421 Ok(input_pipeline)
422 }
423
424 pub fn input_device_bindings(&self) -> &InputDeviceBindingMap {
426 &self.input_device_bindings
427 }
428
429 pub fn input_event_sender(&self) -> &UnboundedSender<Vec<input_device::InputEvent>> {
432 &self.device_event_sender
433 }
434
435 pub fn input_device_types(&self) -> &[input_device::InputDeviceType] {
437 &self.input_device_types
438 }
439
440 pub async fn handle_input_events(mut self) {
442 let metrics_logger_clone = self.metrics_logger.clone();
443 while let Some(input_event) = self.device_event_receiver.next().await {
444 if let Err(e) = self.pipeline_sender.unbounded_send(input_event) {
445 metrics_logger_clone.log_error(
446 InputPipelineErrorMetricDimensionEvent::InputPipelineCouldNotForwardEventFromDriver,
447 std::format!("could not forward event from driver: {:?}", e));
448 }
449 }
450
451 metrics_logger_clone.log_error(
452 InputPipelineErrorMetricDimensionEvent::InputPipelineStopHandlingEvents,
453 "Input pipeline stopped handling input events.".to_string(),
454 );
455 }
456
457 async fn watch_for_devices(
473 mut device_watcher: Watcher,
474 dir_proxy: fio::DirectoryProxy,
475 device_types: &[input_device::InputDeviceType],
476 input_event_sender: UnboundedSender<Vec<input_device::InputEvent>>,
477 bindings: InputDeviceBindingMap,
478 input_devices_node: &fuchsia_inspect::Node,
479 break_on_idle: bool,
480 feature_flags: input_device::InputPipelineFeatureFlags,
481 metrics_logger: metrics::MetricsLogger,
482 ) -> Result<(), Error> {
483 let devices_discovered = input_devices_node.create_uint("devices_discovered", 0);
485 let devices_connected = input_devices_node.create_uint("devices_connected", 0);
486 while let Some(msg) = device_watcher.try_next().await? {
487 if let Ok(instance_name) = msg.filename.into_os_string().into_string() {
488 if instance_name == "." {
489 continue;
490 }
491
492 match msg.event {
493 WatchEvent::EXISTING | WatchEvent::ADD_FILE => {
494 log::info!("found input device {}", instance_name);
495 devices_discovered.add(1);
496 let device_path = Path::new(&instance_name).join("input_device");
497 let device_proxy = match input_device::get_device_from_dir_entry_path(
498 &dir_proxy,
499 &device_path,
500 ) {
501 Ok(proxy) => proxy,
502 Err(e) => {
503 log::error!(
504 "Failed to connect to input device {}: {:?}",
505 instance_name,
506 e
507 );
508 continue;
509 }
510 };
511 add_device_bindings(
512 device_types,
513 &instance_name,
514 device_proxy,
515 &input_event_sender,
516 &bindings,
517 get_next_device_id(),
518 input_devices_node,
519 Some(&devices_connected),
520 feature_flags.clone(),
521 metrics_logger.clone(),
522 )
523 .await;
524 }
525 WatchEvent::IDLE => {
526 if break_on_idle {
527 break;
528 }
529 }
530 _ => (),
531 }
532 }
533 }
534 input_devices_node.record(devices_discovered);
536 input_devices_node.record(devices_connected);
537 Err(format_err!("Input pipeline stopped watching for new input devices."))
538 }
539
540 pub async fn handle_input_device_registry_request_stream(
555 mut stream: fidl_fuchsia_input_injection::InputDeviceRegistryRequestStream,
556 device_types: &[input_device::InputDeviceType],
557 input_event_sender: &UnboundedSender<Vec<input_device::InputEvent>>,
558 bindings: &InputDeviceBindingMap,
559 input_devices_node: &fuchsia_inspect::Node,
560 feature_flags: input_device::InputPipelineFeatureFlags,
561 metrics_logger: metrics::MetricsLogger,
562 ) -> Result<(), Error> {
563 while let Some(request) = stream
564 .try_next()
565 .await
566 .context("Error handling input device registry request stream")?
567 {
568 match request {
569 fidl_fuchsia_input_injection::InputDeviceRegistryRequest::Register {
570 device,
571 ..
572 } => {
573 let device = fidl_next::ClientEnd::<
575 fidl_next_fuchsia_input_report::InputDevice,
576 zx::Channel,
577 >::from_untyped(device.into_channel());
578 let device = Dispatcher::client_from_zx_channel(device);
579 let device = device.spawn();
580 let device_id = get_next_device_id();
581
582 add_device_bindings(
583 device_types,
584 &format!("input-device-registry-{}", device_id),
585 device,
586 input_event_sender,
587 bindings,
588 device_id,
589 input_devices_node,
590 None,
591 feature_flags.clone(),
592 metrics_logger.clone(),
593 )
594 .await;
595 }
596 fidl_fuchsia_input_injection::InputDeviceRegistryRequest::RegisterAndGetDeviceInfo {
597 device,
598 responder,
599 .. } => {
600 let device = fidl_next::ClientEnd::<
602 fidl_next_fuchsia_input_report::InputDevice,
603 zx::Channel,
604 >::from_untyped(device.into_channel());
605 let device = Dispatcher::client_from_zx_channel(device);
606 let device = device.spawn();
607 let device_id = get_next_device_id();
608
609 add_device_bindings(
610 device_types,
611 &format!("input-device-registry-{}", device_id),
612 device,
613 input_event_sender,
614 bindings,
615 device_id,
616 input_devices_node,
617 None,
618 feature_flags.clone(),
619 metrics_logger.clone(),
620 )
621 .await;
622
623 responder.send(fidl_fuchsia_input_injection::InputDeviceRegistryRegisterAndGetDeviceInfoResponse{
624 device_id: Some(device_id),
625 ..Default::default()
626 }).expect("Failed to respond to RegisterAndGetDeviceInfo request");
627 }
628 }
629 }
630
631 Ok(())
632 }
633
634 fn run(
636 mut receiver: UnboundedReceiver<Vec<input_device::InputEvent>>,
637 handlers: Vec<Rc<dyn input_handler::BatchInputHandler>>,
638 metrics_logger: metrics::MetricsLogger,
639 ) -> dispatcher::TaskHandle<()> {
640 Dispatcher::spawn_local(async move {
641 for handler in &handlers {
642 handler.clone().set_handler_healthy();
643 }
644
645 let mut handlers_by_type: [Vec<Rc<dyn input_handler::BatchInputHandler>>;
646 InputEventType::COUNT] = Default::default();
647
648 let event_types = vec![
650 InputEventType::Keyboard,
651 InputEventType::LightSensor,
652 InputEventType::ConsumerControls,
653 InputEventType::Mouse,
654 InputEventType::TouchScreen,
655 InputEventType::Touchpad,
656 #[cfg(test)]
657 InputEventType::Fake,
658 ];
659
660 for event_type in event_types {
661 let handlers_for_type: Vec<Rc<dyn input_handler::BatchInputHandler>> = handlers
662 .iter()
663 .filter(|h| h.interest().contains(&event_type))
664 .cloned()
665 .collect();
666 handlers_by_type[event_type as usize] = handlers_for_type;
667 }
668
669 while let Some(events) = receiver.next().await {
670 if events.is_empty() {
671 continue;
672 }
673
674 let mut groups_seen = 0;
675 let events = events.into_iter().chunk_by(|e| InputEventType::from(&e.device_event));
676 let events = events.into_iter().map(|(k, v)| (k, v.collect::<Vec<_>>()));
677 for (event_type, event_group) in events {
678 groups_seen += 1;
679 if groups_seen == 2 {
680 metrics_logger.log_error(
681 InputPipelineErrorMetricDimensionEvent::InputFrameContainsMultipleTypesOfEvents,
682 "it is not recommended to contain multiple types of events in 1 send".to_string(),
683 );
684 }
685 let mut events_in_group = event_group;
686
687 let handlers = &handlers_by_type[event_type as usize];
689
690 for handler in handlers {
691 events_in_group =
692 handler.clone().handle_input_events(events_in_group).await;
693 }
694
695 for event in events_in_group {
696 if event.handled == input_device::Handled::No {
697 log::warn!("unhandled input event: {:?}", event);
698 }
699 if let Some(trace_id) = event.trace_id {
700 fuchsia_trace::flow_end!(
701 "input",
702 "event_in_input_pipeline",
703 trace_id.into()
704 );
705 }
706 }
707 }
708 }
709 for handler in &handlers {
710 handler.clone().set_handler_unhealthy("Pipeline loop terminated");
711 }
712 panic!("Runner task is not supposed to terminate.")
713 })
714 }
715}
716
717async fn add_device_bindings(
737 device_types: &[input_device::InputDeviceType],
738 instance_name: &str,
739 device_proxy: fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
740 input_event_sender: &UnboundedSender<Vec<input_device::InputEvent>>,
741 bindings: &InputDeviceBindingMap,
742 device_id: u32,
743 input_devices_node: &fuchsia_inspect::Node,
744 devices_connected: Option<&fuchsia_inspect::UintProperty>,
745 feature_flags: InputPipelineFeatureFlags,
746 metrics_logger: metrics::MetricsLogger,
747) {
748 let mut matched_device_types = vec![];
749 if let Ok(res) = device_proxy.get_descriptor().await {
750 for device_type in device_types {
751 if input_device::is_device_type(&res.descriptor, *device_type).await {
752 matched_device_types.push(device_type);
753 match devices_connected {
754 Some(dev_connected) => {
755 let _ = dev_connected.add(1);
756 }
757 None => (),
758 };
759 }
760 }
761 if matched_device_types.is_empty() {
762 log::info!(
763 "device {} did not match any supported device types: {:?}",
764 instance_name,
765 device_types
766 );
767 let device_node =
768 input_devices_node.create_child(format!("{}_Unsupported", instance_name));
769 let mut health = fuchsia_inspect::health::Node::new(&device_node);
770 health.set_unhealthy("Unsupported device type.");
771 device_node.record(health);
772 input_devices_node.record(device_node);
773 return;
774 }
775 } else {
776 metrics_logger.clone().log_error(
777 InputPipelineErrorMetricDimensionEvent::InputPipelineNoDeviceDescriptor,
778 std::format!("cannot bind device {} without a device descriptor", instance_name),
779 );
780 return;
781 }
782
783 log::info!(
784 "binding {} to device types: {}",
785 instance_name,
786 matched_device_types
787 .iter()
788 .fold(String::new(), |device_types_string, device_type| device_types_string
789 + &format!("{:?}, ", device_type))
790 );
791
792 let mut new_bindings: Vec<BoxedInputDeviceBinding> = vec![];
793 for device_type in matched_device_types {
794 let proxy = device_proxy.clone();
815 let device_node =
816 input_devices_node.create_child(format!("{}_{}", instance_name, device_type));
817 match input_device::get_device_binding(
818 *device_type,
819 proxy,
820 device_id,
821 input_event_sender.clone(),
822 device_node,
823 feature_flags.clone(),
824 metrics_logger.clone(),
825 )
826 .await
827 {
828 Ok(binding) => new_bindings.push(binding),
829 Err(e) => {
830 metrics_logger.log_error(
831 InputPipelineErrorMetricDimensionEvent::InputPipelineFailedToBind,
832 std::format!("failed to bind {} as {:?}: {}", instance_name, device_type, e),
833 );
834 }
835 }
836 }
837
838 if !new_bindings.is_empty() {
839 let mut bindings = bindings.lock();
840 if let Some(v) = bindings.get_mut(&device_id) {
841 v.extend(new_bindings);
842 } else {
843 bindings.insert(device_id, new_bindings);
844 }
845 }
846}
847
848#[cfg(test)]
849mod tests {
850 use super::*;
851 use crate::input_device::{InputDeviceBinding, InputEventType};
852 use crate::utils::Position;
853 use crate::{fake_input_device_binding, mouse_binding, observe_fake_events_input_handler};
854 use async_trait::async_trait;
855 use diagnostics_assertions::AnyProperty;
856 use fidl::endpoints::{create_proxy_and_stream, create_request_stream};
857 use fuchsia_async as fasync;
858 use futures::FutureExt;
859 use pretty_assertions::assert_eq;
860 use rand::Rng;
861 use sorted_vec_map::SortedVecSet;
862 use vfs::{pseudo_directory, service as pseudo_fs_service};
863
864 fn send_input_event(
869 sender: UnboundedSender<Vec<input_device::InputEvent>>,
870 ) -> Vec<input_device::InputEvent> {
871 let mut rng = rand::rng();
872 let offset =
873 Position { x: rng.random_range(0..10) as f32, y: rng.random_range(0..10) as f32 };
874 let input_event = input_device::InputEvent {
875 device_event: input_device::InputDeviceEvent::Mouse(mouse_binding::MouseEvent::new(
876 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
877 counts: Position { x: offset.x, y: offset.y },
878 }),
879 None, None, mouse_binding::MousePhase::Move,
882 SortedVecSet::new(),
883 SortedVecSet::new(),
884 None, None, )),
887 device_descriptor: input_device::InputDeviceDescriptor::Mouse(
888 mouse_binding::MouseDeviceDescriptor {
889 device_id: 1,
890 absolute_x_range: None,
891 absolute_y_range: None,
892 wheel_v_range: None,
893 wheel_h_range: None,
894 buttons: None,
895 },
896 ),
897 event_time: zx::MonotonicInstant::get(),
898 handled: input_device::Handled::No,
899 trace_id: None,
900 };
901 match sender.unbounded_send(vec![input_event.clone()]) {
902 Err(_) => assert!(false),
903 _ => {}
904 }
905
906 vec![input_event]
907 }
908
909 fn handle_input_device_request(
914 input_device_request: fidl_fuchsia_input_report::InputDeviceRequest,
915 ) {
916 match input_device_request {
917 fidl_fuchsia_input_report::InputDeviceRequest::GetDescriptor { responder } => {
918 let _ = responder.send(&fidl_fuchsia_input_report::DeviceDescriptor {
919 device_information: None,
920 mouse: Some(fidl_fuchsia_input_report::MouseDescriptor {
921 input: Some(fidl_fuchsia_input_report::MouseInputDescriptor {
922 movement_x: None,
923 movement_y: None,
924 scroll_v: None,
925 scroll_h: None,
926 buttons: Some(vec![0]),
927 position_x: None,
928 position_y: None,
929 ..Default::default()
930 }),
931 ..Default::default()
932 }),
933 sensor: None,
934 touch: None,
935 keyboard: None,
936 consumer_control: None,
937 ..Default::default()
938 });
939 }
940 _ => {}
941 }
942 }
943
944 #[fasync::run_singlethreaded(test)]
946 async fn multiple_devices_single_handler() {
947 let (device_event_sender, device_event_receiver) = futures::channel::mpsc::unbounded();
949 let first_device_binding =
950 fake_input_device_binding::FakeInputDeviceBinding::new(device_event_sender.clone());
951 let second_device_binding =
952 fake_input_device_binding::FakeInputDeviceBinding::new(device_event_sender.clone());
953
954 let (handler_event_sender, mut handler_event_receiver) =
956 futures::channel::mpsc::channel(100);
957 let input_handler = observe_fake_events_input_handler::ObserveFakeEventsInputHandler::new(
958 handler_event_sender,
959 );
960
961 let (sender, receiver, handlers, _, _, _) =
963 InputPipelineAssembly::new(metrics::MetricsLogger::default())
964 .add_handler(input_handler)
965 .into_components();
966 let inspector = fuchsia_inspect::Inspector::default();
967 let test_node = inspector.root().create_child("input_pipeline");
968 let input_pipeline = InputPipeline {
969 pipeline_sender: sender,
970 device_event_sender,
971 device_event_receiver,
972 input_device_types: vec![],
973 input_device_bindings: Arc::new(Mutex::new(SortedVecMap::new())),
974 inspect_node: test_node,
975 metrics_logger: metrics::MetricsLogger::default(),
976 feature_flags: input_device::InputPipelineFeatureFlags::default(),
977 _tasks: vec![],
978 _fasync_tasks: vec![],
979 };
980 let _runner_task =
981 InputPipeline::run(receiver, handlers, metrics::MetricsLogger::default());
982
983 let first_device_events = send_input_event(first_device_binding.input_event_sender());
985 let second_device_events = send_input_event(second_device_binding.input_event_sender());
986
987 let _pipeline_task = fasync::Task::local(async {
989 input_pipeline.handle_input_events().await;
990 });
991
992 let first_handled_event = handler_event_receiver.next().await;
994 assert_eq!(first_handled_event, first_device_events.into_iter().next());
995
996 let second_handled_event = handler_event_receiver.next().await;
997 assert_eq!(second_handled_event, second_device_events.into_iter().next());
998 }
999
1000 #[fasync::run_singlethreaded(test)]
1002 async fn single_device_multiple_handlers() {
1003 let (device_event_sender, device_event_receiver) = futures::channel::mpsc::unbounded();
1005 let input_device_binding =
1006 fake_input_device_binding::FakeInputDeviceBinding::new(device_event_sender.clone());
1007
1008 let (first_handler_event_sender, mut first_handler_event_receiver) =
1010 futures::channel::mpsc::channel(100);
1011 let first_input_handler =
1012 observe_fake_events_input_handler::ObserveFakeEventsInputHandler::new(
1013 first_handler_event_sender,
1014 );
1015 let (second_handler_event_sender, mut second_handler_event_receiver) =
1016 futures::channel::mpsc::channel(100);
1017 let second_input_handler =
1018 observe_fake_events_input_handler::ObserveFakeEventsInputHandler::new(
1019 second_handler_event_sender,
1020 );
1021
1022 let (sender, receiver, handlers, _, _, _) =
1024 InputPipelineAssembly::new(metrics::MetricsLogger::default())
1025 .add_handler(first_input_handler)
1026 .add_handler(second_input_handler)
1027 .into_components();
1028 let inspector = fuchsia_inspect::Inspector::default();
1029 let test_node = inspector.root().create_child("input_pipeline");
1030 let input_pipeline = InputPipeline {
1031 pipeline_sender: sender,
1032 device_event_sender,
1033 device_event_receiver,
1034 input_device_types: vec![],
1035 input_device_bindings: Arc::new(Mutex::new(SortedVecMap::new())),
1036 inspect_node: test_node,
1037 metrics_logger: metrics::MetricsLogger::default(),
1038 feature_flags: input_device::InputPipelineFeatureFlags::default(),
1039 _tasks: vec![],
1040 _fasync_tasks: vec![],
1041 };
1042 let _runner_task =
1043 InputPipeline::run(receiver, handlers, metrics::MetricsLogger::default());
1044
1045 let input_events = send_input_event(input_device_binding.input_event_sender());
1047
1048 let _pipeline_task = fasync::Task::local(async {
1050 input_pipeline.handle_input_events().await;
1051 });
1052
1053 let expected_event = input_events.into_iter().next();
1055 let first_handler_event = first_handler_event_receiver.next().await;
1056 assert_eq!(first_handler_event, expected_event);
1057 let second_handler_event = second_handler_event_receiver.next().await;
1058 assert_eq!(second_handler_event, expected_event);
1059 }
1060
1061 #[fasync::run_singlethreaded(test)]
1064 async fn watch_devices_one_match_exists() {
1065 let mut count: i8 = 0;
1067 let dir = pseudo_directory! {
1068 "instance_0" => pseudo_directory! {
1069 "input_device" => pseudo_fs_service::host(
1070 move |mut request_stream: fidl_fuchsia_input_report::InputDeviceRequestStream| {
1071 async move {
1072 while count < 3 {
1073 if let Some(input_device_request) =
1074 request_stream.try_next().await.unwrap()
1075 {
1076 handle_input_device_request(input_device_request);
1077 count += 1;
1078 }
1079 }
1080
1081 }.boxed()
1082 },
1083 )
1084 }
1085 };
1086
1087 let dir_proxy_for_watcher = vfs::directory::serve_read_only(
1089 dir.clone(),
1090 vfs::execution_scope::ExecutionScope::new(),
1091 );
1092 let device_watcher = Watcher::new(&dir_proxy_for_watcher).await.unwrap();
1093 let dir_proxy_for_pipeline =
1096 vfs::directory::serve_read_only(dir, vfs::execution_scope::ExecutionScope::new());
1097
1098 let (input_event_sender, _input_event_receiver) = futures::channel::mpsc::unbounded();
1099 let bindings: InputDeviceBindingMap = Arc::new(Mutex::new(SortedVecMap::new()));
1100 let supported_device_types = vec![input_device::InputDeviceType::Mouse];
1101
1102 let inspector = fuchsia_inspect::Inspector::default();
1103 let test_node = inspector.root().create_child("input_pipeline");
1104 test_node.record_string(
1105 "supported_input_devices",
1106 supported_device_types.clone().iter().join(", "),
1107 );
1108 let input_devices = test_node.create_child("input_devices");
1109 diagnostics_assertions::assert_data_tree!(inspector, root: {
1111 input_pipeline: {
1112 supported_input_devices: "Mouse",
1113 input_devices: {}
1114 }
1115 });
1116
1117 let _ = InputPipeline::watch_for_devices(
1118 device_watcher,
1119 dir_proxy_for_pipeline,
1120 &supported_device_types,
1121 input_event_sender,
1122 bindings.clone(),
1123 &input_devices,
1124 true, InputPipelineFeatureFlags { enable_merge_touch_events: false },
1126 metrics::MetricsLogger::default(),
1127 )
1128 .await;
1129
1130 let bindings_map = bindings.lock();
1132 assert_eq!(bindings_map.len(), 1);
1133 let bindings_vector = bindings_map.get(&10);
1134 assert!(bindings_vector.is_some());
1135 assert_eq!(bindings_vector.unwrap().len(), 1);
1136 let boxed_mouse_binding = bindings_vector.unwrap().get(0);
1137 assert!(boxed_mouse_binding.is_some());
1138 assert_eq!(
1139 boxed_mouse_binding.unwrap().get_device_descriptor(),
1140 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1141 device_id: 10,
1142 absolute_x_range: None,
1143 absolute_y_range: None,
1144 wheel_v_range: None,
1145 wheel_h_range: None,
1146 buttons: Some(vec![0]),
1147 })
1148 );
1149
1150 diagnostics_assertions::assert_data_tree!(inspector, root: {
1152 input_pipeline: {
1153 supported_input_devices: "Mouse",
1154 input_devices: {
1155 devices_discovered: 1u64,
1156 devices_connected: 1u64,
1157 "instance_0_Mouse": contains {
1158 reports_received_count: 0u64,
1159 reports_filtered_count: 0u64,
1160 events_generated: 0u64,
1161 last_received_timestamp_ns: 0u64,
1162 last_generated_timestamp_ns: 0u64,
1163 "fuchsia.inspect.Health": {
1164 status: "OK",
1165 start_timestamp_nanos: AnyProperty
1168 },
1169 }
1170 }
1171 }
1172 });
1173 }
1174
1175 #[fasync::run_singlethreaded(test)]
1178 async fn watch_devices_no_matches_exist() {
1179 let mut count: i8 = 0;
1181 let dir = pseudo_directory! {
1182 "instance_0" => pseudo_directory! {
1183 "input_device" => pseudo_fs_service::host(
1184 move |mut request_stream: fidl_fuchsia_input_report::InputDeviceRequestStream| {
1185 async move {
1186 while count < 1 {
1187 if let Some(input_device_request) =
1188 request_stream.try_next().await.unwrap()
1189 {
1190 handle_input_device_request(input_device_request);
1191 count += 1;
1192 }
1193 }
1194
1195 }.boxed()
1196 },
1197 )
1198 }
1199 };
1200
1201 let dir_proxy_for_watcher = vfs::directory::serve_read_only(
1203 dir.clone(),
1204 vfs::execution_scope::ExecutionScope::new(),
1205 );
1206 let device_watcher = Watcher::new(&dir_proxy_for_watcher).await.unwrap();
1207 let dir_proxy_for_pipeline =
1210 vfs::directory::serve_read_only(dir, vfs::execution_scope::ExecutionScope::new());
1211
1212 let (input_event_sender, _input_event_receiver) = futures::channel::mpsc::unbounded();
1213 let bindings: InputDeviceBindingMap = Arc::new(Mutex::new(SortedVecMap::new()));
1214 let supported_device_types = vec![input_device::InputDeviceType::Keyboard];
1215
1216 let inspector = fuchsia_inspect::Inspector::default();
1217 let test_node = inspector.root().create_child("input_pipeline");
1218 test_node.record_string(
1219 "supported_input_devices",
1220 supported_device_types.clone().iter().join(", "),
1221 );
1222 let input_devices = test_node.create_child("input_devices");
1223 diagnostics_assertions::assert_data_tree!(inspector, root: {
1225 input_pipeline: {
1226 supported_input_devices: "Keyboard",
1227 input_devices: {}
1228 }
1229 });
1230
1231 let _ = InputPipeline::watch_for_devices(
1232 device_watcher,
1233 dir_proxy_for_pipeline,
1234 &supported_device_types,
1235 input_event_sender,
1236 bindings.clone(),
1237 &input_devices,
1238 true, InputPipelineFeatureFlags { enable_merge_touch_events: false },
1240 metrics::MetricsLogger::default(),
1241 )
1242 .await;
1243
1244 let bindings = bindings.lock();
1246 assert_eq!(bindings.len(), 0);
1247
1248 diagnostics_assertions::assert_data_tree!(inspector, root: {
1250 input_pipeline: {
1251 supported_input_devices: "Keyboard",
1252 input_devices: {
1253 devices_discovered: 1u64,
1254 devices_connected: 0u64,
1255 "instance_0_Unsupported": {
1256 "fuchsia.inspect.Health": {
1257 status: "UNHEALTHY",
1258 message: "Unsupported device type.",
1259 start_timestamp_nanos: AnyProperty
1262 },
1263 }
1264 }
1265 }
1266 });
1267 }
1268
1269 #[fasync::run_singlethreaded(test)]
1272 async fn handle_input_device_registry_request_stream() {
1273 let (input_device_registry_proxy, input_device_registry_request_stream) =
1274 create_proxy_and_stream::<fidl_fuchsia_input_injection::InputDeviceRegistryMarker>();
1275 let (input_device_client_end, mut input_device_request_stream) =
1276 create_request_stream::<fidl_fuchsia_input_report::InputDeviceMarker>();
1277
1278 let device_types = vec![input_device::InputDeviceType::Mouse];
1279 let (input_event_sender, _input_event_receiver) = futures::channel::mpsc::unbounded();
1280 let bindings: InputDeviceBindingMap = Arc::new(Mutex::new(SortedVecMap::new()));
1281
1282 let mut count: i8 = 0;
1284 let _task = fasync::Task::local(async move {
1285 let _ = input_device_registry_proxy.register(input_device_client_end);
1287
1288 while count < 3 {
1289 if let Some(input_device_request) =
1290 input_device_request_stream.try_next().await.unwrap()
1291 {
1292 handle_input_device_request(input_device_request);
1293 count += 1;
1294 }
1295 }
1296
1297 input_device_registry_proxy.take_event_stream();
1299 });
1300
1301 let inspector = fuchsia_inspect::Inspector::default();
1302 let test_node = inspector.root().create_child("input_pipeline");
1303
1304 let bindings_clone = bindings.clone();
1306 let _ = InputPipeline::handle_input_device_registry_request_stream(
1307 input_device_registry_request_stream,
1308 &device_types,
1309 &input_event_sender,
1310 &bindings_clone,
1311 &test_node,
1312 InputPipelineFeatureFlags { enable_merge_touch_events: false },
1313 metrics::MetricsLogger::default(),
1314 )
1315 .await;
1316
1317 let bindings = bindings.lock();
1319 assert_eq!(bindings.len(), 1);
1320 }
1321
1322 #[fasync::run_singlethreaded(test)]
1324 async fn check_inspect_node_has_correct_properties() {
1325 let device_types = vec![
1326 input_device::InputDeviceType::Touch,
1327 input_device::InputDeviceType::ConsumerControls,
1328 ];
1329 let inspector = fuchsia_inspect::Inspector::default();
1330 let test_node = inspector.root().create_child("input_pipeline");
1331 let (fake_handler_event_sender, _fake_handler_event_receiver) =
1333 futures::channel::mpsc::channel(100);
1334 let fake_input_handler =
1335 observe_fake_events_input_handler::ObserveFakeEventsInputHandler::new(
1336 fake_handler_event_sender,
1337 );
1338 let assembly = InputPipelineAssembly::new(metrics::MetricsLogger::default())
1339 .add_handler(fake_input_handler);
1340 let _test_input_pipeline = InputPipeline::new(
1341 &Incoming::new(),
1342 device_types,
1343 assembly,
1344 test_node,
1345 InputPipelineFeatureFlags { enable_merge_touch_events: false },
1346 metrics::MetricsLogger::default(),
1347 );
1348 diagnostics_assertions::assert_data_tree!(inspector, root: {
1349 input_pipeline: {
1350 supported_input_devices: "Touch, ConsumerControls",
1351 handlers_registered: 1u64,
1352 handlers_healthy: 1u64,
1353 input_devices: {}
1354 }
1355 });
1356 }
1357
1358 struct SpecificInterestFakeHandler {
1359 interest_types: Vec<input_device::InputEventType>,
1360 event_sender: std::cell::RefCell<futures::channel::mpsc::Sender<input_device::InputEvent>>,
1361 }
1362
1363 impl SpecificInterestFakeHandler {
1364 pub fn new(
1365 interest_types: Vec<input_device::InputEventType>,
1366 event_sender: futures::channel::mpsc::Sender<input_device::InputEvent>,
1367 ) -> Rc<Self> {
1368 Rc::new(SpecificInterestFakeHandler {
1369 interest_types,
1370 event_sender: std::cell::RefCell::new(event_sender),
1371 })
1372 }
1373 }
1374
1375 impl Handler for SpecificInterestFakeHandler {
1376 fn set_handler_healthy(self: std::rc::Rc<Self>) {}
1377 fn set_handler_unhealthy(self: std::rc::Rc<Self>, _msg: &str) {}
1378 fn get_name(&self) -> &'static str {
1379 "SpecificInterestFakeHandler"
1380 }
1381
1382 fn interest(&self) -> Vec<input_device::InputEventType> {
1383 self.interest_types.clone()
1384 }
1385 }
1386
1387 #[async_trait(?Send)]
1388 impl input_handler::InputHandler for SpecificInterestFakeHandler {
1389 async fn handle_input_event(
1390 self: Rc<Self>,
1391 input_event: input_device::InputEvent,
1392 ) -> Vec<input_device::InputEvent> {
1393 match self.event_sender.borrow_mut().try_send(input_event.clone()) {
1394 Err(e) => panic!("SpecificInterestFakeHandler failed to send event: {:?}", e),
1395 Ok(_) => {}
1396 }
1397 vec![input_event]
1398 }
1399 }
1400
1401 #[fasync::run_singlethreaded(test)]
1402 async fn run_only_sends_events_to_interested_handlers() {
1403 let (mouse_sender, mut mouse_receiver) = futures::channel::mpsc::channel(1);
1405 let mouse_handler =
1406 SpecificInterestFakeHandler::new(vec![InputEventType::Mouse], mouse_sender);
1407
1408 let (fake_sender, mut fake_receiver) = futures::channel::mpsc::channel(1);
1410 let fake_handler =
1411 SpecificInterestFakeHandler::new(vec![InputEventType::Fake], fake_sender);
1412
1413 let (pipeline_sender, pipeline_receiver, handlers, _, _, _) =
1414 InputPipelineAssembly::new(metrics::MetricsLogger::default())
1415 .add_handler(mouse_handler)
1416 .add_handler(fake_handler)
1417 .into_components();
1418
1419 let _runner_task =
1421 InputPipeline::run(pipeline_receiver, handlers, metrics::MetricsLogger::default());
1422
1423 let fake_event = input_device::InputEvent {
1425 device_event: input_device::InputDeviceEvent::Fake,
1426 device_descriptor: input_device::InputDeviceDescriptor::Fake,
1427 event_time: zx::MonotonicInstant::get(),
1428 handled: input_device::Handled::No,
1429 trace_id: None,
1430 };
1431
1432 pipeline_sender.unbounded_send(vec![fake_event.clone()]).expect("failed to send event");
1434
1435 let received_by_fake = fake_receiver.next().await;
1437 assert_eq!(received_by_fake, Some(fake_event));
1438
1439 assert!(mouse_receiver.try_next().is_err());
1441 }
1442
1443 fn create_mouse_event(x: f32, y: f32) -> input_device::InputEvent {
1444 input_device::InputEvent {
1445 device_event: input_device::InputDeviceEvent::Mouse(mouse_binding::MouseEvent::new(
1446 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1447 counts: Position { x, y },
1448 }),
1449 None,
1450 None,
1451 mouse_binding::MousePhase::Move,
1452 SortedVecSet::new(),
1453 SortedVecSet::new(),
1454 None,
1455 None,
1456 )),
1457 device_descriptor: input_device::InputDeviceDescriptor::Mouse(
1458 mouse_binding::MouseDeviceDescriptor {
1459 device_id: 1,
1460 absolute_x_range: None,
1461 absolute_y_range: None,
1462 wheel_v_range: None,
1463 wheel_h_range: None,
1464 buttons: None,
1465 },
1466 ),
1467 event_time: zx::MonotonicInstant::get(),
1468 handled: input_device::Handled::No,
1469 trace_id: None,
1470 }
1471 }
1472
1473 #[fasync::run_singlethreaded(test)]
1474 async fn run_mixed_event_types_dispatched_correctly() {
1475 let (mouse_sender, mut mouse_receiver) = futures::channel::mpsc::channel(10);
1477 let mouse_handler =
1478 SpecificInterestFakeHandler::new(vec![InputEventType::Mouse], mouse_sender);
1479
1480 let (fake_sender, mut fake_receiver) = futures::channel::mpsc::channel(10);
1482 let fake_handler =
1483 SpecificInterestFakeHandler::new(vec![InputEventType::Fake], fake_sender);
1484
1485 let (pipeline_sender, pipeline_receiver, handlers, _, _, _) =
1486 InputPipelineAssembly::new(metrics::MetricsLogger::default())
1487 .add_handler(mouse_handler)
1488 .add_handler(fake_handler)
1489 .into_components();
1490
1491 let _runner_task =
1493 InputPipeline::run(pipeline_receiver, handlers, metrics::MetricsLogger::default());
1494
1495 let mouse_event_1 = create_mouse_event(1.0, 1.0);
1497 let mouse_event_2 = create_mouse_event(2.0, 2.0);
1498 let mouse_event_3 = create_mouse_event(3.0, 3.0);
1499
1500 let fake_event_1 = input_device::InputEvent {
1501 device_event: input_device::InputDeviceEvent::Fake,
1502 device_descriptor: input_device::InputDeviceDescriptor::Fake,
1503 event_time: zx::MonotonicInstant::get(),
1504 handled: input_device::Handled::No,
1505 trace_id: None,
1506 };
1507
1508 let mixed_batch = vec![
1511 mouse_event_1.clone(),
1512 mouse_event_2.clone(),
1513 fake_event_1.clone(),
1514 mouse_event_3.clone(),
1515 ];
1516 pipeline_sender.unbounded_send(mixed_batch).expect("failed to send events");
1517
1518 assert_eq!(mouse_receiver.next().await, Some(mouse_event_1));
1520 assert_eq!(mouse_receiver.next().await, Some(mouse_event_2));
1521 assert_eq!(mouse_receiver.next().await, Some(mouse_event_3));
1522
1523 assert_eq!(fake_receiver.next().await, Some(fake_event_1));
1525 }
1526}