1use crate::input_device::{self, InputEvent, UnhandledInputEvent};
6use crate::input_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
255#[async_trait(?Send)]
256impl UnhandledInputHandler for DisplayOwnership {
257 async fn handle_unhandled_input_event(
258 self: Rc<Self>,
259 unhandled_input_event: UnhandledInputEvent,
260 ) -> Vec<input_device::InputEvent> {
261 fuchsia_trace::duration!("input", "display_ownership");
262 self.inspect_status.count_received_event(&unhandled_input_event.event_time);
263 match unhandled_input_event.device_event {
264 input_device::InputDeviceEvent::Keyboard(ref e) => {
265 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
266 }
267 _ => {
268 log::warn!("Unhandled input event: {:?}", unhandled_input_event.get_event_type());
270 }
271 }
272 let is_display_ownership_lost = self.is_display_ownership_lost();
273 if is_display_ownership_lost {
274 self.inspect_status.count_handled_event();
275 }
276
277 #[cfg(test)]
278 {
279 if let Some(loop_done) = self.loop_done.borrow().as_ref() {
280 loop_done.unbounded_send(()).unwrap();
281 }
282 }
283
284 vec![
285 input_device::InputEvent::from(unhandled_input_event)
286 .into_handled_if(is_display_ownership_lost),
287 ]
288 }
289
290 fn set_handler_healthy(self: std::rc::Rc<Self>) {
291 self.inspect_status.health_node.borrow_mut().set_ok();
292 }
293
294 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
295 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
296 }
297
298 fn get_name(&self) -> &'static str {
299 "DisplayOwnership"
300 }
301
302 fn interest(&self) -> Vec<input_device::InputEventType> {
303 vec![input_device::InputEventType::Keyboard]
304 }
305}
306
307fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
308 input_device::InputDeviceDescriptor::Keyboard(
309 KeyboardDeviceDescriptor {
311 keys: vec![],
312 device_information: fidl_fuchsia_input_report::DeviceInformation {
313 vendor_id: Some(0),
314 product_id: Some(0),
315 version: Some(0),
316 polling_rate: Some(0),
317 ..Default::default()
318 },
319 device_id: 0,
320 },
321 )
322}
323
324fn into_input_event(
325 keyboard_event: KeyboardEvent,
326 event_time: MonotonicInstant,
327) -> input_device::InputEvent {
328 input_device::InputEvent {
329 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
330 device_descriptor: empty_keyboard_device_descriptor(),
331 event_time,
332 handled: input_device::Handled::No,
333 trace_id: None,
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340 use crate::testing_utilities::{create_fake_input_event, create_input_event};
341 use fidl_fuchsia_input::Key;
342 use fuchsia_async as fasync;
343 use pretty_assertions::assert_eq;
344 use std::convert::TryFrom as _;
345 use zx::{EventPair, Peered};
346
347 struct DisplayWrangler {
351 event: EventPair,
352 last: Signals,
353 }
354
355 impl DisplayWrangler {
356 fn new(event: EventPair) -> Self {
357 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
358 instance.set_unowned();
362 instance
363 }
364
365 fn set_unowned(&mut self) {
366 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
367 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
368 self.last = *DISPLAY_UNOWNED;
369 }
370
371 fn set_owned(&mut self) {
372 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
373 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
374 self.last = *DISPLAY_OWNED;
375 }
376 }
377
378 #[fuchsia::test]
379 async fn display_ownership_change() {
380 let (test_event, handler_event) = EventPair::create();
384
385 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
387
388 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
390
391 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
394
395 let mut wrangler = DisplayWrangler::new(test_event);
398 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
399
400 let handler_clone = handler.clone();
401 let handler_sender_clone = handler_sender.clone();
402 let _task = fasync::Task::local(async move {
403 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
404 });
405
406 let handler_clone_2 = handler.clone();
407 let _input_task = fasync::Task::local(async move {
408 let mut receiver = handler_receiver;
409 while let Some(event) = receiver.next().await {
410 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
411 let out_events =
412 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
413 for out_event in out_events {
414 handler_sender.unbounded_send(out_event).unwrap();
415 }
416 }
417 });
418
419 let fake_time = MonotonicInstant::from_nanos(42);
420
421 wrangler.set_owned();
425 loop_done.next().await;
426 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
427 loop_done.next().await;
428
429 wrangler.set_unowned();
431 loop_done.next().await;
432 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
433 loop_done.next().await;
434
435 wrangler.set_owned();
437 loop_done.next().await;
438 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
439 loop_done.next().await;
440
441 wrangler.set_unowned();
443 loop_done.next().await;
444 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
445 loop_done.next().await;
446
447 let actual: Vec<InputEvent> =
448 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
449
450 assert_eq!(
451 actual,
452 vec![
453 create_fake_input_event(fake_time),
455 create_fake_input_event(fake_time).into_handled(),
457 create_fake_input_event(fake_time),
459 create_fake_input_event(fake_time).into_handled(),
461 ]
462 );
463 }
464
465 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
466 let fake_time = MonotonicInstant::from_nanos(42);
467 create_input_event(
468 KeyboardEvent::new(key, event_type),
469 &input_device::InputDeviceDescriptor::Fake,
470 fake_time,
471 input_device::Handled::No,
472 )
473 }
474
475 #[fuchsia::test]
476 async fn basic_key_state_handling() {
477 let (test_event, handler_event) = EventPair::create();
478 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
479 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
480 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
481 let mut wrangler = DisplayWrangler::new(test_event);
482 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
483
484 let handler_clone = handler.clone();
485 let handler_sender_clone = handler_sender.clone();
486 let _task = fasync::Task::local(async move {
487 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
488 });
489
490 let handler_clone_2 = handler.clone();
491 let _input_task = fasync::Task::local(async move {
492 let mut receiver = handler_receiver;
493 while let Some(event) = receiver.next().await {
494 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
495 let out_events =
496 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
497 for out_event in out_events {
498 handler_sender.unbounded_send(out_event).unwrap();
499 }
500 }
501 });
502
503 let fake_time = MonotonicInstant::from_nanos(42);
504
505 wrangler.set_owned();
507 loop_done.next().await;
508 test_sender
509 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
510 .unwrap();
511 loop_done.next().await;
512
513 wrangler.set_unowned();
515 loop_done.next().await;
516
517 wrangler.set_owned();
519 loop_done.next().await;
520
521 test_sender
523 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
524 .unwrap();
525 loop_done.next().await;
526
527 let actual: Vec<InputEvent> =
528 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
529
530 assert_eq!(
531 actual,
532 vec![
533 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
534 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
535 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
536 new_keyboard_input_event(Key::A, KeyEventType::Sync)
537 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
538 new_keyboard_input_event(Key::A, KeyEventType::Released),
539 ]
540 );
541 }
542
543 #[fuchsia::test]
544 async fn more_key_state_handling() {
545 let (test_event, handler_event) = EventPair::create();
546 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
547 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
548 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
549 let mut wrangler = DisplayWrangler::new(test_event);
550 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
551
552 let handler_clone = handler.clone();
553 let handler_sender_clone = handler_sender.clone();
554 let _task = fasync::Task::local(async move {
555 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
556 });
557
558 let handler_clone_2 = handler.clone();
559 let _input_task = fasync::Task::local(async move {
560 let mut receiver = handler_receiver;
561 while let Some(event) = receiver.next().await {
562 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
563 let out_events =
564 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
565 for out_event in out_events {
566 handler_sender.unbounded_send(out_event).unwrap();
567 }
568 }
569 });
570
571 let fake_time = MonotonicInstant::from_nanos(42);
572
573 wrangler.set_owned();
574 loop_done.next().await;
575 test_sender
576 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
577 .unwrap();
578 loop_done.next().await;
579 test_sender
580 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
581 .unwrap();
582 loop_done.next().await;
583
584 wrangler.set_unowned();
586 loop_done.next().await;
587 test_sender
588 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
589 .unwrap();
590 loop_done.next().await;
591 test_sender
592 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
593 .unwrap();
594 loop_done.next().await;
595
596 wrangler.set_owned();
598 loop_done.next().await;
599
600 test_sender
602 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
603 .unwrap();
604 loop_done.next().await;
605 test_sender
606 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
607 .unwrap();
608 loop_done.next().await;
609
610 let actual: Vec<InputEvent> =
611 test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;
612
613 assert_eq!(
614 actual,
615 vec![
616 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
617 new_keyboard_input_event(Key::B, KeyEventType::Pressed),
618 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
619 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
620 new_keyboard_input_event(Key::B, KeyEventType::Cancel)
621 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
622 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
623 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
624 new_keyboard_input_event(Key::A, KeyEventType::Sync)
628 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
629 new_keyboard_input_event(Key::C, KeyEventType::Sync)
630 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
631 new_keyboard_input_event(Key::A, KeyEventType::Released),
632 new_keyboard_input_event(Key::C, KeyEventType::Released),
633 ]
634 );
635 }
636
637 #[fuchsia::test]
638 async fn display_ownership_initialized_with_inspect_node() {
639 let (test_event, handler_event) = EventPair::create();
640 let (loop_done_sender, _) = mpsc::unbounded::<()>();
641 let inspector = fuchsia_inspect::Inspector::default();
642 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
643 let _ = DisplayWrangler::new(test_event);
645 let _handler = DisplayOwnership::new_internal(
646 handler_event,
647 Some(loop_done_sender),
648 &fake_handlers_node,
649 );
650 diagnostics_assertions::assert_data_tree!(inspector, root: {
651 input_handlers_node: {
652 display_ownership: {
653 events_received_count: 0u64,
654 events_handled_count: 0u64,
655 last_received_timestamp_ns: 0u64,
656 "fuchsia.inspect.Health": {
657 status: "STARTING_UP",
658 start_timestamp_nanos: diagnostics_assertions::AnyProperty
661 },
662 }
663 }
664 });
665 }
666
667 #[fuchsia::test]
668 async fn display_ownership_inspect_counts_events() {
669 let (test_event, handler_event) = EventPair::create();
670 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
671 let (handler_sender, _test_receiver) = mpsc::unbounded::<InputEvent>();
672 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
673 let mut wrangler = DisplayWrangler::new(test_event);
674 let inspector = fuchsia_inspect::Inspector::default();
675 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
676 let handler = DisplayOwnership::new_internal(
677 handler_event,
678 Some(loop_done_sender),
679 &fake_handlers_node,
680 );
681 let handler_clone = handler.clone();
682 let handler_sender_clone = handler_sender.clone();
683 let _task = fasync::Task::local(async move {
684 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
685 });
686
687 let handler_clone_2 = handler.clone();
688 let _input_task = fasync::Task::local(async move {
689 let mut receiver = handler_receiver;
690 while let Some(event) = receiver.next().await {
691 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
692 let out_events =
693 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
694 for out_event in out_events {
695 handler_sender.unbounded_send(out_event).unwrap();
696 }
697 }
698 });
699
700 wrangler.set_owned();
702 loop_done.next().await;
703 test_sender
704 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
705 .unwrap();
706 loop_done.next().await;
707
708 wrangler.set_unowned();
711 loop_done.next().await;
712 test_sender
713 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
714 .unwrap();
715 loop_done.next().await;
716
717 wrangler.set_owned();
719 loop_done.next().await;
720
721 test_sender
723 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
724 .unwrap();
725 loop_done.next().await;
726
727 diagnostics_assertions::assert_data_tree!(inspector, root: {
728 input_handlers_node: {
729 display_ownership: {
730 events_received_count: 3u64,
731 events_handled_count: 1u64,
732 last_received_timestamp_ns: 42u64,
733 "fuchsia.inspect.Health": {
734 status: "STARTING_UP",
735 start_timestamp_nanos: diagnostics_assertions::AnyProperty
738 },
739 }
740 }
741 });
742 }
743}