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