1use crate::input_device::{self, InputEvent, UnhandledInputEvent};
6use crate::input_handler::{Handler, InputHandlerStatus, UnhandledInputHandler};
7use crate::keyboard_binding::{KeyboardDeviceDescriptor, KeyboardEvent};
8use anyhow::{Context, Result};
9use async_trait::async_trait;
10use fidl_fuchsia_ui_composition_internal as fcomp;
11use fidl_fuchsia_ui_input3::KeyEventType;
12use fuchsia_async::{OnSignals, Task};
13use fuchsia_inspect::health::Reporter;
14use futures::StreamExt;
15use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
16use keymaps::KeyState;
17use std::cell::RefCell;
18use std::rc::Rc;
19use std::sync::LazyLock;
20use zx::{AsHandleRef, MonotonicDuration, MonotonicInstant, Signals, Status};
21
22static DISPLAY_OWNED: LazyLock<Signals> = LazyLock::new(|| {
25 Signals::from_bits(fcomp::SIGNAL_DISPLAY_OWNED).expect("static init should not fail")
26});
27
28static DISPLAY_UNOWNED: LazyLock<Signals> = LazyLock::new(|| {
31 Signals::from_bits(fcomp::SIGNAL_DISPLAY_NOT_OWNED).expect("static init should not fail")
32});
33
34static ANY_DISPLAY_EVENT: LazyLock<Signals> = LazyLock::new(|| *DISPLAY_OWNED | *DISPLAY_UNOWNED);
36
37#[derive(Debug, Clone, PartialEq)]
39struct Ownership {
40 signals: Signals,
41}
42
43impl std::convert::From<Signals> for Ownership {
44 fn from(signals: Signals) -> Self {
45 Ownership { signals }
46 }
47}
48
49impl Ownership {
50 fn is_display_ownership_lost(&self) -> bool {
53 self.signals.contains(*DISPLAY_UNOWNED)
54 }
55
56 fn next_signal(&self) -> Signals {
60 match self.is_display_ownership_lost() {
61 true => *DISPLAY_OWNED,
62 false => *DISPLAY_UNOWNED,
63 }
64 }
65
66 async fn wait_ownership_change<'a, T: AsHandleRef>(
71 &self,
72 event: &'a T,
73 ) -> Result<Signals, Status> {
74 OnSignals::new(event, self.next_signal()).await
75 }
76}
77
78pub struct DisplayOwnership {
98 ownership: Rc<RefCell<Ownership>>,
101
102 key_state: RefCell<KeyState>,
104
105 display_ownership_change_receiver: RefCell<Option<UnboundedReceiver<Ownership>>>,
107
108 _display_ownership_task: Task<()>,
111
112 inspect_status: InputHandlerStatus,
114
115 #[cfg(test)]
121 loop_done: RefCell<Option<UnboundedSender<()>>>,
122}
123
124impl DisplayOwnership {
125 pub fn new(
132 display_ownership_event: impl AsHandleRef + 'static,
133 input_handlers_node: &fuchsia_inspect::Node,
134 ) -> Rc<Self> {
135 DisplayOwnership::new_internal(display_ownership_event, None, input_handlers_node)
136 }
137
138 #[cfg(test)]
139 pub fn new_for_test(
140 display_ownership_event: impl AsHandleRef + 'static,
141 loop_done: UnboundedSender<()>,
142 ) -> Rc<Self> {
143 let inspector = fuchsia_inspect::Inspector::default();
144 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
145 DisplayOwnership::new_internal(
146 display_ownership_event,
147 Some(loop_done),
148 &fake_handlers_node,
149 )
150 }
151
152 fn new_internal(
153 display_ownership_event: impl AsHandleRef + 'static,
154 _loop_done: Option<UnboundedSender<()>>,
155 input_handlers_node: &fuchsia_inspect::Node,
156 ) -> Rc<Self> {
157 let initial_state = display_ownership_event
158 .as_handle_ref()
161 .wait_one(*ANY_DISPLAY_EVENT, MonotonicInstant::INFINITE_PAST)
162 .expect("unable to set the initial display state");
163 log::debug!("setting initial display ownership to: {:?}", &initial_state);
164 let initial_ownership: Ownership = initial_state.into();
165 let ownership = Rc::new(RefCell::new(initial_ownership.clone()));
166
167 let mut ownership_clone = initial_ownership;
168 let (ownership_sender, ownership_receiver) = mpsc::unbounded();
169 let display_ownership_task = Task::local(async move {
170 loop {
171 let signals = ownership_clone.wait_ownership_change(&display_ownership_event).await;
172 match signals {
173 Err(e) => {
174 log::warn!("could not read display state: {:?}", e);
175 break;
176 }
177 Ok(signals) => {
178 log::debug!("setting display ownership to: {:?}", &signals);
179 ownership_sender.unbounded_send(signals.into()).unwrap();
180 ownership_clone = signals.into();
181 }
182 }
183 }
184 log::warn!(
185 "display loop exiting and will no longer monitor display changes - this is not expected"
186 );
187 });
188 log::info!("Display ownership handler installed");
189 let inspect_status = InputHandlerStatus::new(
190 input_handlers_node,
191 "display_ownership",
192 false,
193 );
194 Rc::new(Self {
195 ownership,
196 key_state: RefCell::new(KeyState::new()),
197 display_ownership_change_receiver: RefCell::new(Some(ownership_receiver)),
198 _display_ownership_task: display_ownership_task,
199 inspect_status,
200 #[cfg(test)]
201 loop_done: RefCell::new(_loop_done),
202 })
203 }
204
205 fn is_display_ownership_lost(&self) -> bool {
207 self.ownership.borrow().is_display_ownership_lost()
208 }
209
210 pub async fn handle_ownership_change(
217 self: &Rc<Self>,
218 output: UnboundedSender<InputEvent>,
219 ) -> Result<()> {
220 let mut ownership_source = self
221 .display_ownership_change_receiver
222 .borrow_mut()
223 .take()
224 .context("display_ownership_change_receiver already taken")?;
225 while let Some(new_ownership) = ownership_source.next().await {
226 let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
227 let event_type = match is_display_ownership_lost {
231 true => KeyEventType::Cancel,
232 false => KeyEventType::Sync,
233 };
234 let keys = self.key_state.borrow().get_set();
235 let mut event_time = MonotonicInstant::get();
236 for key in keys.into_iter() {
237 let key_event = KeyboardEvent::new(key, event_type);
238 output
239 .unbounded_send(into_input_event(key_event, event_time))
240 .context("unable to send display updates")?;
241 event_time = event_time + MonotonicDuration::from_nanos(1);
242 }
243 *(self.ownership.borrow_mut()) = new_ownership;
244 #[cfg(test)]
245 {
246 if let Some(loop_done) = self.loop_done.borrow().as_ref() {
247 loop_done.unbounded_send(()).unwrap();
248 }
249 }
250 }
251 Ok(())
252 }
253}
254
255impl Handler for DisplayOwnership {
256 fn set_handler_healthy(self: std::rc::Rc<Self>) {
257 self.inspect_status.health_node.borrow_mut().set_ok();
258 }
259
260 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
261 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
262 }
263
264 fn get_name(&self) -> &'static str {
265 "DisplayOwnership"
266 }
267
268 fn interest(&self) -> Vec<input_device::InputEventType> {
269 vec![input_device::InputEventType::Keyboard]
270 }
271}
272
273#[async_trait(?Send)]
274impl UnhandledInputHandler for DisplayOwnership {
275 async fn handle_unhandled_input_event(
276 self: Rc<Self>,
277 unhandled_input_event: UnhandledInputEvent,
278 ) -> Vec<input_device::InputEvent> {
279 fuchsia_trace::duration!("input", "display_ownership");
280 self.inspect_status.count_received_event(&unhandled_input_event.event_time);
281 match unhandled_input_event.device_event {
282 input_device::InputDeviceEvent::Keyboard(ref e) => {
283 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
284 }
285 _ => {
286 log::warn!("Unhandled input event: {:?}", unhandled_input_event.get_event_type());
288 }
289 }
290 let is_display_ownership_lost = self.is_display_ownership_lost();
291 if is_display_ownership_lost {
292 self.inspect_status.count_handled_event();
293 }
294
295 #[cfg(test)]
296 {
297 if let Some(loop_done) = self.loop_done.borrow().as_ref() {
298 loop_done.unbounded_send(()).unwrap();
299 }
300 }
301
302 vec![
303 input_device::InputEvent::from(unhandled_input_event)
304 .into_handled_if(is_display_ownership_lost),
305 ]
306 }
307}
308
309fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
310 input_device::InputDeviceDescriptor::Keyboard(
311 KeyboardDeviceDescriptor {
313 keys: vec![],
314 device_information: fidl_fuchsia_input_report::DeviceInformation {
315 vendor_id: Some(0),
316 product_id: Some(0),
317 version: Some(0),
318 polling_rate: Some(0),
319 ..Default::default()
320 },
321 device_id: 0,
322 },
323 )
324}
325
326fn into_input_event(
327 keyboard_event: KeyboardEvent,
328 event_time: MonotonicInstant,
329) -> input_device::InputEvent {
330 input_device::InputEvent {
331 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
332 device_descriptor: empty_keyboard_device_descriptor(),
333 event_time,
334 handled: input_device::Handled::No,
335 trace_id: None,
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342 use crate::testing_utilities::{create_fake_input_event, create_input_event};
343 use fidl_fuchsia_input::Key;
344 use fuchsia_async as fasync;
345 use pretty_assertions::assert_eq;
346 use std::convert::TryFrom as _;
347 use zx::{EventPair, Peered};
348
349 struct DisplayWrangler {
353 event: EventPair,
354 last: Signals,
355 }
356
357 impl DisplayWrangler {
358 fn new(event: EventPair) -> Self {
359 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
360 instance.set_unowned();
364 instance
365 }
366
367 fn set_unowned(&mut self) {
368 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
369 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
370 self.last = *DISPLAY_UNOWNED;
371 }
372
373 fn set_owned(&mut self) {
374 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
375 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
376 self.last = *DISPLAY_OWNED;
377 }
378 }
379
380 #[fuchsia::test]
381 async fn display_ownership_change() {
382 let (test_event, handler_event) = EventPair::create();
386
387 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
389
390 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
392
393 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
396
397 let mut wrangler = DisplayWrangler::new(test_event);
400 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
401
402 let handler_clone = handler.clone();
403 let handler_sender_clone = handler_sender.clone();
404 let _task = fasync::Task::local(async move {
405 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
406 });
407
408 let handler_clone_2 = handler.clone();
409 let _input_task = fasync::Task::local(async move {
410 let mut receiver = handler_receiver;
411 while let Some(event) = receiver.next().await {
412 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
413 let out_events =
414 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
415 for out_event in out_events {
416 handler_sender.unbounded_send(out_event).unwrap();
417 }
418 }
419 });
420
421 let fake_time = MonotonicInstant::from_nanos(42);
422
423 wrangler.set_owned();
427 loop_done.next().await;
428 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
429 loop_done.next().await;
430
431 wrangler.set_unowned();
433 loop_done.next().await;
434 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
435 loop_done.next().await;
436
437 wrangler.set_owned();
439 loop_done.next().await;
440 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
441 loop_done.next().await;
442
443 wrangler.set_unowned();
445 loop_done.next().await;
446 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
447 loop_done.next().await;
448
449 let actual: Vec<InputEvent> =
450 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
451
452 assert_eq!(
453 actual,
454 vec![
455 create_fake_input_event(fake_time),
457 create_fake_input_event(fake_time).into_handled(),
459 create_fake_input_event(fake_time),
461 create_fake_input_event(fake_time).into_handled(),
463 ]
464 );
465 }
466
467 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
468 let fake_time = MonotonicInstant::from_nanos(42);
469 create_input_event(
470 KeyboardEvent::new(key, event_type),
471 &input_device::InputDeviceDescriptor::Fake,
472 fake_time,
473 input_device::Handled::No,
474 )
475 }
476
477 #[fuchsia::test]
478 async fn basic_key_state_handling() {
479 let (test_event, handler_event) = EventPair::create();
480 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
481 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
482 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
483 let mut wrangler = DisplayWrangler::new(test_event);
484 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
485
486 let handler_clone = handler.clone();
487 let handler_sender_clone = handler_sender.clone();
488 let _task = fasync::Task::local(async move {
489 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
490 });
491
492 let handler_clone_2 = handler.clone();
493 let _input_task = fasync::Task::local(async move {
494 let mut receiver = handler_receiver;
495 while let Some(event) = receiver.next().await {
496 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
497 let out_events =
498 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
499 for out_event in out_events {
500 handler_sender.unbounded_send(out_event).unwrap();
501 }
502 }
503 });
504
505 let fake_time = MonotonicInstant::from_nanos(42);
506
507 wrangler.set_owned();
509 loop_done.next().await;
510 test_sender
511 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
512 .unwrap();
513 loop_done.next().await;
514
515 wrangler.set_unowned();
517 loop_done.next().await;
518
519 wrangler.set_owned();
521 loop_done.next().await;
522
523 test_sender
525 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
526 .unwrap();
527 loop_done.next().await;
528
529 let actual: Vec<InputEvent> =
530 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
531
532 assert_eq!(
533 actual,
534 vec![
535 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
536 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
537 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
538 new_keyboard_input_event(Key::A, KeyEventType::Sync)
539 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
540 new_keyboard_input_event(Key::A, KeyEventType::Released),
541 ]
542 );
543 }
544
545 #[fuchsia::test]
546 async fn more_key_state_handling() {
547 let (test_event, handler_event) = EventPair::create();
548 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
549 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
550 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
551 let mut wrangler = DisplayWrangler::new(test_event);
552 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
553
554 let handler_clone = handler.clone();
555 let handler_sender_clone = handler_sender.clone();
556 let _task = fasync::Task::local(async move {
557 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
558 });
559
560 let handler_clone_2 = handler.clone();
561 let _input_task = fasync::Task::local(async move {
562 let mut receiver = handler_receiver;
563 while let Some(event) = receiver.next().await {
564 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
565 let out_events =
566 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
567 for out_event in out_events {
568 handler_sender.unbounded_send(out_event).unwrap();
569 }
570 }
571 });
572
573 let fake_time = MonotonicInstant::from_nanos(42);
574
575 wrangler.set_owned();
576 loop_done.next().await;
577 test_sender
578 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
579 .unwrap();
580 loop_done.next().await;
581 test_sender
582 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
583 .unwrap();
584 loop_done.next().await;
585
586 wrangler.set_unowned();
588 loop_done.next().await;
589 test_sender
590 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
591 .unwrap();
592 loop_done.next().await;
593 test_sender
594 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
595 .unwrap();
596 loop_done.next().await;
597
598 wrangler.set_owned();
600 loop_done.next().await;
601
602 test_sender
604 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
605 .unwrap();
606 loop_done.next().await;
607 test_sender
608 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
609 .unwrap();
610 loop_done.next().await;
611
612 let actual: Vec<InputEvent> =
613 test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;
614
615 assert_eq!(
616 actual,
617 vec![
618 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
619 new_keyboard_input_event(Key::B, KeyEventType::Pressed),
620 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
621 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
622 new_keyboard_input_event(Key::B, KeyEventType::Cancel)
623 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
624 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
625 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
626 new_keyboard_input_event(Key::A, KeyEventType::Sync)
630 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
631 new_keyboard_input_event(Key::C, KeyEventType::Sync)
632 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
633 new_keyboard_input_event(Key::A, KeyEventType::Released),
634 new_keyboard_input_event(Key::C, KeyEventType::Released),
635 ]
636 );
637 }
638
639 #[fuchsia::test]
640 async fn display_ownership_initialized_with_inspect_node() {
641 let (test_event, handler_event) = EventPair::create();
642 let (loop_done_sender, _) = mpsc::unbounded::<()>();
643 let inspector = fuchsia_inspect::Inspector::default();
644 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
645 let _ = DisplayWrangler::new(test_event);
647 let _handler = DisplayOwnership::new_internal(
648 handler_event,
649 Some(loop_done_sender),
650 &fake_handlers_node,
651 );
652 diagnostics_assertions::assert_data_tree!(inspector, root: {
653 input_handlers_node: {
654 display_ownership: {
655 events_received_count: 0u64,
656 events_handled_count: 0u64,
657 last_received_timestamp_ns: 0u64,
658 "fuchsia.inspect.Health": {
659 status: "STARTING_UP",
660 start_timestamp_nanos: diagnostics_assertions::AnyProperty
663 },
664 }
665 }
666 });
667 }
668
669 #[fuchsia::test]
670 async fn display_ownership_inspect_counts_events() {
671 let (test_event, handler_event) = EventPair::create();
672 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
673 let (handler_sender, _test_receiver) = mpsc::unbounded::<InputEvent>();
674 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
675 let mut wrangler = DisplayWrangler::new(test_event);
676 let inspector = fuchsia_inspect::Inspector::default();
677 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
678 let handler = DisplayOwnership::new_internal(
679 handler_event,
680 Some(loop_done_sender),
681 &fake_handlers_node,
682 );
683 let handler_clone = handler.clone();
684 let handler_sender_clone = handler_sender.clone();
685 let _task = fasync::Task::local(async move {
686 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
687 });
688
689 let handler_clone_2 = handler.clone();
690 let _input_task = fasync::Task::local(async move {
691 let mut receiver = handler_receiver;
692 while let Some(event) = receiver.next().await {
693 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
694 let out_events =
695 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
696 for out_event in out_events {
697 handler_sender.unbounded_send(out_event).unwrap();
698 }
699 }
700 });
701
702 wrangler.set_owned();
704 loop_done.next().await;
705 test_sender
706 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
707 .unwrap();
708 loop_done.next().await;
709
710 wrangler.set_unowned();
713 loop_done.next().await;
714 test_sender
715 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
716 .unwrap();
717 loop_done.next().await;
718
719 wrangler.set_owned();
721 loop_done.next().await;
722
723 test_sender
725 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
726 .unwrap();
727 loop_done.next().await;
728
729 diagnostics_assertions::assert_data_tree!(inspector, root: {
730 input_handlers_node: {
731 display_ownership: {
732 events_received_count: 3u64,
733 events_handled_count: 1u64,
734 last_received_timestamp_ns: 42u64,
735 "fuchsia.inspect.Health": {
736 status: "STARTING_UP",
737 start_timestamp_nanos: diagnostics_assertions::AnyProperty
740 },
741 }
742 }
743 });
744 }
745}