1use crate::input_device::{self, Handled, InputDeviceBinding, InputDeviceStatus, InputEvent};
6use crate::{autorepeater, metrics};
7use anyhow::{format_err, Error, Result};
8use async_trait::async_trait;
9use fidl_fuchsia_input_report::{InputDeviceProxy, InputReport};
10use fidl_fuchsia_ui_input3::KeyEventType;
11use fuchsia_inspect::health::Reporter;
12use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
13use metrics_registry::*;
14use {fidl_fuchsia_ui_input3 as fidl_ui_input3, fuchsia_async as fasync};
15
16#[derive(Clone, Debug, PartialEq)]
32pub struct KeyboardEvent {
33 key: fidl_fuchsia_input::Key,
35
36 event_type: KeyEventType,
38
39 modifiers: Option<fidl_ui_input3::Modifiers>,
41
42 lock_state: Option<fidl_ui_input3::LockState>,
44
45 keymap: Option<String>,
48
49 key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>,
54
55 repeat_sequence: u32,
61
62 autorepeat_settings: Option<autorepeater::Settings>,
64}
65
66impl KeyboardEvent {
67 pub fn new(key: fidl_fuchsia_input::Key, event_type: KeyEventType) -> Self {
70 KeyboardEvent {
71 key,
72 event_type,
73 modifiers: None,
74 lock_state: None,
75 keymap: None,
76 key_meaning: None,
77 repeat_sequence: 0,
78 autorepeat_settings: Default::default(),
79 }
80 }
81
82 pub fn into_with_autorepeat_settings(
84 self,
85 autorepeat_settings: Option<autorepeater::Settings>,
86 ) -> Self {
87 Self { autorepeat_settings, ..self }
88 }
89
90 pub fn get_autorepeat_settings(&self) -> autorepeater::Settings {
91 self.autorepeat_settings.unwrap_or(Default::default())
92 }
93
94 pub fn get_key(&self) -> fidl_fuchsia_input::Key {
95 self.key
96 }
97
98 pub fn into_with_key(self, key: fidl_fuchsia_input::Key) -> Self {
100 Self { key, ..self }
101 }
102
103 pub fn get_event_type(&self) -> KeyEventType {
104 self.event_type
105 }
106
107 pub fn into_with_event_type(self, event_type: KeyEventType) -> Self {
109 Self { event_type, ..self }
110 }
111
112 pub fn into_with_folded_event(self) -> Self {
114 Self { event_type: self.get_event_type_folded(), ..self }
115 }
116
117 pub fn get_event_type_folded(&self) -> KeyEventType {
119 match self.event_type {
120 KeyEventType::Pressed | KeyEventType::Sync => KeyEventType::Pressed,
121 KeyEventType::Released | KeyEventType::Cancel => KeyEventType::Released,
122 }
123 }
124
125 pub fn into_with_modifiers(self, modifiers: Option<fidl_ui_input3::Modifiers>) -> Self {
127 Self { modifiers, ..self }
128 }
129
130 pub fn get_modifiers(&self) -> Option<fidl_ui_input3::Modifiers> {
132 self.modifiers
133 }
134
135 pub fn get_unsided_modifiers(&self) -> fidl_fuchsia_ui_input3::Modifiers {
139 use fidl_fuchsia_ui_input3::Modifiers;
140 let mut modifiers = self.modifiers.unwrap_or(Modifiers::empty());
141 modifiers.set(
142 Modifiers::LEFT_ALT
143 | Modifiers::LEFT_CTRL
144 | Modifiers::LEFT_SHIFT
145 | Modifiers::LEFT_META
146 | Modifiers::RIGHT_ALT
147 | Modifiers::RIGHT_CTRL
148 | Modifiers::RIGHT_SHIFT
149 | Modifiers::RIGHT_META,
150 false,
151 );
152 modifiers
153 }
154
155 pub fn into_with_lock_state(self, lock_state: Option<fidl_ui_input3::LockState>) -> Self {
157 Self { lock_state, ..self }
158 }
159
160 pub fn get_lock_state(&self) -> Option<fidl_ui_input3::LockState> {
162 self.lock_state
163 }
164
165 pub fn into_with_keymap(self, keymap: Option<String>) -> Self {
168 Self { keymap, ..self }
169 }
170
171 pub fn get_keymap(&self) -> Option<String> {
173 self.keymap.clone()
174 }
175
176 pub fn into_with_key_meaning(
178 self,
179 key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>,
180 ) -> Self {
181 Self { key_meaning, ..self }
182 }
183
184 pub fn get_key_meaning(&self) -> Option<fidl_fuchsia_ui_input3::KeyMeaning> {
186 self.key_meaning
187 }
188
189 pub fn get_repeat_sequence(&self) -> u32 {
193 self.repeat_sequence
194 }
195
196 pub fn into_with_repeat_sequence(self, repeat_sequence: u32) -> Self {
199 Self { repeat_sequence, ..self }
200 }
201
202 #[cfg(test)]
204 pub(crate) fn from_key_event_at_time(
205 &self,
206 event_time: zx::MonotonicInstant,
207 ) -> fidl_ui_input3::KeyEvent {
208 fidl_ui_input3::KeyEvent {
209 timestamp: Some(event_time.into_nanos()),
210 type_: Some(self.event_type),
211 key: Some(self.key),
212 modifiers: self.modifiers,
213 lock_state: self.lock_state,
214 repeat_sequence: Some(self.repeat_sequence),
215 key_meaning: self.key_meaning,
216 ..Default::default()
217 }
218 }
219}
220
221impl KeyboardEvent {
222 pub fn same_key(this: &KeyboardEvent, that: &KeyboardEvent) -> bool {
224 this.get_key() == that.get_key()
225 }
226}
227
228#[derive(Clone, Debug, PartialEq)]
230pub struct KeyboardDeviceDescriptor {
231 pub keys: Vec<fidl_fuchsia_input::Key>,
233
234 pub device_information: fidl_fuchsia_input_report::DeviceInformation,
236
237 pub device_id: u32,
239}
240
241#[cfg(test)]
242impl Default for KeyboardDeviceDescriptor {
243 fn default() -> Self {
244 KeyboardDeviceDescriptor {
245 keys: vec![],
246 device_information: fidl_fuchsia_input_report::DeviceInformation {
247 vendor_id: Some(0),
248 product_id: Some(0),
249 version: Some(0),
250 polling_rate: Some(0),
251 ..Default::default()
252 },
253 device_id: 0,
254 }
255 }
256}
257
258pub struct KeyboardBinding {
264 event_sender: UnboundedSender<input_device::InputEvent>,
266
267 device_descriptor: KeyboardDeviceDescriptor,
269}
270
271#[async_trait]
272impl input_device::InputDeviceBinding for KeyboardBinding {
273 fn input_event_sender(&self) -> UnboundedSender<input_device::InputEvent> {
274 self.event_sender.clone()
275 }
276
277 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
278 input_device::InputDeviceDescriptor::Keyboard(self.device_descriptor.clone())
279 }
280}
281
282impl KeyboardBinding {
283 pub async fn new(
298 device_proxy: InputDeviceProxy,
299 device_id: u32,
300 input_event_sender: UnboundedSender<input_device::InputEvent>,
301 device_node: fuchsia_inspect::Node,
302 metrics_logger: metrics::MetricsLogger,
303 ) -> Result<Self, Error> {
304 let (device_binding, mut inspect_status) = Self::bind_device(
305 &device_proxy,
306 input_event_sender,
307 device_id,
308 device_node,
309 metrics_logger.clone(),
310 )
311 .await?;
312 inspect_status.health_node.set_ok();
313 input_device::initialize_report_stream(
314 device_proxy,
315 device_binding.get_device_descriptor(),
316 device_binding.input_event_sender(),
317 inspect_status,
318 metrics_logger,
319 Self::process_reports,
320 );
321
322 Ok(device_binding)
323 }
324
325 pub fn to_modifiers(keys: &[&fidl_fuchsia_input::Key]) -> Option<fidl_ui_input3::Modifiers> {
336 let mut modifiers = fidl_ui_input3::Modifiers::empty();
337 for key in keys {
338 let modifier = match key {
339 fidl_fuchsia_input::Key::CapsLock => Some(fidl_ui_input3::Modifiers::CAPS_LOCK),
340 fidl_fuchsia_input::Key::NumLock => Some(fidl_ui_input3::Modifiers::NUM_LOCK),
341 fidl_fuchsia_input::Key::ScrollLock => Some(fidl_ui_input3::Modifiers::SCROLL_LOCK),
342 _ => None,
343 };
344 if let Some(modifier) = modifier {
345 modifiers.insert(modifier);
346 };
347 }
348 if modifiers.is_empty() {
349 return None;
350 }
351 Some(modifiers)
352 }
353
354 async fn bind_device(
366 device: &InputDeviceProxy,
367 input_event_sender: UnboundedSender<input_device::InputEvent>,
368 device_id: u32,
369 device_node: fuchsia_inspect::Node,
370 metrics_logger: metrics::MetricsLogger,
371 ) -> Result<(Self, InputDeviceStatus), Error> {
372 let mut input_device_status = InputDeviceStatus::new(device_node);
373 let descriptor = match device.get_descriptor().await {
374 Ok(descriptor) => descriptor,
375 Err(_) => {
376 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
377 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
378 }
379 };
380
381 let device_info = descriptor.device_information.ok_or_else(|| {
382 input_device_status.health_node.set_unhealthy("Empty device_information in descriptor");
383 metrics_logger.log_error(
386 InputPipelineErrorMetricDimensionEvent::KeyboardEmptyDeviceInfo,
387 std::format!("DRIVER BUG: empty device_information for device_id: {}", device_id),
388 );
389 format_err!("empty device info for device_id: {}", device_id)
390 })?;
391 match descriptor.keyboard {
392 Some(fidl_fuchsia_input_report::KeyboardDescriptor {
393 input: Some(fidl_fuchsia_input_report::KeyboardInputDescriptor { keys3, .. }),
394 output: _,
395 ..
396 }) => Ok((
397 KeyboardBinding {
398 event_sender: input_event_sender,
399 device_descriptor: KeyboardDeviceDescriptor {
400 keys: keys3.unwrap_or_default(),
401 device_information: device_info,
402 device_id,
403 },
404 },
405 input_device_status,
406 )),
407 device_descriptor => {
408 input_device_status
409 .health_node
410 .set_unhealthy("Keyboard Device Descriptor failed to parse.");
411 Err(format_err!(
412 "Keyboard Device Descriptor failed to parse: \n {:?}",
413 device_descriptor
414 ))
415 }
416 }
417 }
418
419 fn process_reports(
439 report: InputReport,
440 previous_report: Option<InputReport>,
441 device_descriptor: &input_device::InputDeviceDescriptor,
442 input_event_sender: &mut UnboundedSender<input_device::InputEvent>,
443 inspect_status: &InputDeviceStatus,
444 metrics_logger: &metrics::MetricsLogger,
445 ) -> (Option<InputReport>, Option<UnboundedReceiver<InputEvent>>) {
446 fuchsia_trace::duration!(c"input", c"keyboard-binding-process-report");
447 if let Some(trace_id) = report.trace_id {
448 fuchsia_trace::flow_end!(c"input", c"input_report", trace_id.into());
449 }
450
451 let tracing_id = match report.trace_id {
452 Some(id) => id.into(),
453 None => fuchsia_trace::Id::new(),
454 };
455 fuchsia_trace::flow_begin!(c"input", c"key_event_thread", tracing_id);
456
457 inspect_status.count_received_report(&report);
458 match &report.keyboard {
460 None => {
461 inspect_status.count_filtered_report();
462 return (previous_report, None);
463 }
464 _ => (),
465 };
466
467 let new_keys = match KeyboardBinding::parse_pressed_keys(&report) {
468 Some(keys) => keys,
469 None => {
470 metrics_logger.log_error(
476 InputPipelineErrorMetricDimensionEvent::KeyboardFailedToParse,
477 std::format!("Failed to parse keyboard keys: {:?}", report),
478 );
479 inspect_status.count_filtered_report();
480 return (previous_report, None);
481 }
482 };
483
484 let previous_keys: Vec<fidl_fuchsia_input::Key> = previous_report
485 .as_ref()
486 .and_then(|unwrapped_report| KeyboardBinding::parse_pressed_keys(&unwrapped_report))
487 .unwrap_or_default();
488
489 let (inspect_sender, inspect_receiver) = futures::channel::mpsc::unbounded();
490
491 KeyboardBinding::send_key_events(
492 &new_keys,
493 &previous_keys,
494 device_descriptor.clone(),
495 zx::MonotonicInstant::get(),
496 input_event_sender.clone(),
497 inspect_sender,
498 metrics_logger,
499 tracing_id,
500 );
501
502 (Some(report), Some(inspect_receiver))
503 }
504
505 fn parse_pressed_keys(input_report: &InputReport) -> Option<Vec<fidl_fuchsia_input::Key>> {
515 input_report
516 .keyboard
517 .as_ref()
518 .and_then(|unwrapped_keyboard| unwrapped_keyboard.pressed_keys3.as_ref())
519 .and_then(|unwrapped_keys| Some(unwrapped_keys.iter().cloned().collect()))
520 }
521
522 fn send_key_events(
531 new_keys: &Vec<fidl_fuchsia_input::Key>,
532 previous_keys: &Vec<fidl_fuchsia_input::Key>,
533 device_descriptor: input_device::InputDeviceDescriptor,
534 event_time: zx::MonotonicInstant,
535 input_event_sender: UnboundedSender<input_device::InputEvent>,
536 inspect_sender: UnboundedSender<input_device::InputEvent>,
537 metrics_logger: &metrics::MetricsLogger,
538 tracing_id: fuchsia_trace::Id,
539 ) {
540 fn dispatch_events(
544 key_events: Vec<(fidl_fuchsia_input::Key, fidl_fuchsia_ui_input3::KeyEventType)>,
545 device_descriptor: input_device::InputDeviceDescriptor,
546 event_time: zx::MonotonicInstant,
547 input_event_sender: UnboundedSender<input_device::InputEvent>,
548 inspect_sender: UnboundedSender<input_device::InputEvent>,
549 metrics_logger: metrics::MetricsLogger,
550 tracing_id: fuchsia_trace::Id,
551 ) {
552 fasync::Task::local(async move {
553 fuchsia_trace::duration!(c"input", c"key_event_thread");
554 fuchsia_trace::flow_end!(c"input", c"key_event_thread", tracing_id);
555
556 let mut event_time = event_time;
557 for (key, event_type) in key_events.into_iter() {
558 let trace_id = fuchsia_trace::Id::new();
559 fuchsia_trace::duration!(c"input", c"keyboard_event_in_binding");
560 fuchsia_trace::flow_begin!(c"input", c"event_in_input_pipeline", trace_id);
561
562 let event = input_device::InputEvent {
563 device_event: input_device::InputDeviceEvent::Keyboard(
564 KeyboardEvent::new(key, event_type),
565 ),
566 device_descriptor: device_descriptor.clone(),
567 event_time,
568 handled: Handled::No,
569 trace_id: Some(trace_id),
570 };
571 match input_event_sender.unbounded_send(event.clone()) {
572 Err(error) => {
573 metrics_logger.log_error(
574 InputPipelineErrorMetricDimensionEvent::KeyboardFailedToSendKeyboardEvent,
575 std::format!(
576 "Failed to send KeyboardEvent for key: {:?}, event_type: {:?}: {:?}",
577 &key,
578 &event_type,
579 error));
580 }
581 _ => { let _ = inspect_sender.unbounded_send(event).expect("Failed to count generated KeyboardEvent in Input Pipeline Inspect tree."); },
582 }
583 event_time = event_time + zx::MonotonicDuration::from_nanos(1);
588 }
589 })
590 .detach();
591 }
592
593 let pressed_keys = new_keys
596 .iter()
597 .cloned()
598 .filter(|key| !previous_keys.contains(key))
599 .map(|k| (k, fidl_fuchsia_ui_input3::KeyEventType::Pressed));
600
601 let released_keys = previous_keys
604 .iter()
605 .cloned()
606 .filter(|key| !new_keys.contains(key))
607 .map(|k| (k, fidl_fuchsia_ui_input3::KeyEventType::Released));
608
609 let all_keys = released_keys.chain(pressed_keys).collect::<Vec<_>>();
614
615 dispatch_events(
616 all_keys,
617 device_descriptor,
618 event_time,
619 input_event_sender,
620 inspect_sender,
621 metrics_logger.clone(),
622 tracing_id,
623 );
624 }
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630 use crate::testing_utilities;
631 use fuchsia_async as fasync;
632 use futures::StreamExt;
633
634 #[fasync::run_singlethreaded(test)]
637 async fn pressed_key() {
638 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
639 keys: vec![fidl_fuchsia_input::Key::A],
640 ..Default::default()
641 });
642 let (event_time_i64, _) = testing_utilities::event_times();
643
644 let reports = vec![testing_utilities::create_keyboard_input_report(
645 vec![fidl_fuchsia_input::Key::A],
646 event_time_i64,
647 )];
648 let expected_events = vec![testing_utilities::create_keyboard_event(
649 fidl_fuchsia_input::Key::A,
650 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
651 None,
652 &descriptor,
653 None,
654 )];
655
656 assert_input_report_sequence_generates_events!(
657 input_reports: reports,
658 expected_events: expected_events,
659 device_descriptor: descriptor,
660 device_type: KeyboardBinding,
661 );
662 }
663
664 #[fasync::run_singlethreaded(test)]
667 async fn released_key() {
668 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
669 keys: vec![fidl_fuchsia_input::Key::A],
670 ..Default::default()
671 });
672 let (event_time_i64, _) = testing_utilities::event_times();
673
674 let reports = vec![
675 testing_utilities::create_keyboard_input_report(
676 vec![fidl_fuchsia_input::Key::A],
677 event_time_i64,
678 ),
679 testing_utilities::create_keyboard_input_report(vec![], event_time_i64),
680 ];
681
682 let expected_events = vec![
683 testing_utilities::create_keyboard_event(
684 fidl_fuchsia_input::Key::A,
685 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
686 None,
687 &descriptor,
688 None,
689 ),
690 testing_utilities::create_keyboard_event(
691 fidl_fuchsia_input::Key::A,
692 fidl_fuchsia_ui_input3::KeyEventType::Released,
693 None,
694 &descriptor,
695 None,
696 ),
697 ];
698
699 assert_input_report_sequence_generates_events!(
700 input_reports: reports,
701 expected_events: expected_events,
702 device_descriptor: descriptor.clone(),
703 device_type: KeyboardBinding,
704 );
705 }
706
707 #[fasync::run_singlethreaded(test)]
710 async fn multiple_pressed_event_filtering() {
711 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
712 keys: vec![fidl_fuchsia_input::Key::A],
713 ..Default::default()
714 });
715 let (event_time_i64, _) = testing_utilities::event_times();
716
717 let reports = vec![
718 testing_utilities::create_keyboard_input_report(
719 vec![fidl_fuchsia_input::Key::A],
720 event_time_i64,
721 ),
722 testing_utilities::create_keyboard_input_report(
723 vec![fidl_fuchsia_input::Key::A],
724 event_time_i64,
725 ),
726 ];
727
728 let expected_events = vec![testing_utilities::create_keyboard_event(
729 fidl_fuchsia_input::Key::A,
730 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
731 None,
732 &descriptor,
733 None,
734 )];
735
736 assert_input_report_sequence_generates_events!(
737 input_reports: reports,
738 expected_events: expected_events,
739 device_descriptor: descriptor,
740 device_type: KeyboardBinding,
741 );
742 }
743
744 #[fasync::run_singlethreaded(test)]
746 async fn pressed_and_released_keys() {
747 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
748 keys: vec![fidl_fuchsia_input::Key::A, fidl_fuchsia_input::Key::B],
749 ..Default::default()
750 });
751 let (event_time_i64, _) = testing_utilities::event_times();
752
753 let reports = vec![
754 testing_utilities::create_keyboard_input_report(
755 vec![fidl_fuchsia_input::Key::A],
756 event_time_i64,
757 ),
758 testing_utilities::create_keyboard_input_report(
759 vec![fidl_fuchsia_input::Key::B],
760 event_time_i64,
761 ),
762 ];
763
764 let expected_events = vec![
765 testing_utilities::create_keyboard_event(
766 fidl_fuchsia_input::Key::A,
767 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
768 None,
769 &descriptor,
770 None,
771 ),
772 testing_utilities::create_keyboard_event(
773 fidl_fuchsia_input::Key::A,
774 fidl_fuchsia_ui_input3::KeyEventType::Released,
775 None,
776 &descriptor,
777 None,
778 ),
779 testing_utilities::create_keyboard_event(
780 fidl_fuchsia_input::Key::B,
781 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
782 None,
783 &descriptor,
784 None,
785 ),
786 ];
787
788 assert_input_report_sequence_generates_events!(
789 input_reports: reports,
790 expected_events: expected_events,
791 device_descriptor: descriptor,
792 device_type: KeyboardBinding,
793 );
794 }
795
796 #[fuchsia::test]
797 fn get_unsided_modifiers() {
798 use fidl_ui_input3::Modifiers;
799 let event = KeyboardEvent::new(fidl_fuchsia_input::Key::A, KeyEventType::Pressed)
800 .into_with_modifiers(Some(Modifiers::all()));
801 assert_eq!(
802 event.get_unsided_modifiers(),
803 Modifiers::CAPS_LOCK
804 | Modifiers::NUM_LOCK
805 | Modifiers::SCROLL_LOCK
806 | Modifiers::FUNCTION
807 | Modifiers::SYMBOL
808 | Modifiers::SHIFT
809 | Modifiers::ALT
810 | Modifiers::ALT_GRAPH
811 | Modifiers::META
812 | Modifiers::CTRL
813 )
814 }
815
816 #[fuchsia::test]
817 fn conversion_fills_out_all_fields() {
818 use fidl_fuchsia_input::Key;
819 use fidl_ui_input3::{KeyMeaning, LockState, Modifiers, NonPrintableKey};
820 let event = KeyboardEvent::new(Key::A, KeyEventType::Pressed)
821 .into_with_modifiers(Some(Modifiers::all()))
822 .into_with_lock_state(Some(LockState::all()))
823 .into_with_repeat_sequence(42)
824 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(NonPrintableKey::Tab)));
825
826 let actual = event.from_key_event_at_time(zx::MonotonicInstant::from_nanos(42));
827 assert_eq!(
828 actual,
829 fidl_fuchsia_ui_input3::KeyEvent {
830 timestamp: Some(42),
831 type_: Some(KeyEventType::Pressed),
832 key: Some(Key::A),
833 modifiers: Some(Modifiers::all()),
834 key_meaning: Some(KeyMeaning::NonPrintableKey(NonPrintableKey::Tab)),
835 repeat_sequence: Some(42),
836 lock_state: Some(LockState::all()),
837 ..Default::default()
838 }
839 );
840 }
841}