1use crate::input_device::{self, InputEvent};
6use crate::input_handler::InputHandlerStatus;
7use crate::keyboard_binding::{KeyboardDeviceDescriptor, KeyboardEvent};
8use anyhow::{Context, Result};
9use fidl_fuchsia_ui_composition_internal as fcomp;
10use fidl_fuchsia_ui_input3::KeyEventType;
11use fuchsia_async::{OnSignals, Task};
12use fuchsia_inspect::health::Reporter;
13use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
14use futures::{StreamExt, select};
15use keymaps::KeyState;
16use std::cell::RefCell;
17use std::rc::Rc;
18use std::sync::LazyLock;
19use zx::{AsHandleRef, MonotonicDuration, MonotonicInstant, Signals, Status};
20
21static DISPLAY_OWNED: LazyLock<Signals> = LazyLock::new(|| {
24 Signals::from_bits(fcomp::SIGNAL_DISPLAY_OWNED).expect("static init should not fail")
25});
26
27static DISPLAY_UNOWNED: LazyLock<Signals> = LazyLock::new(|| {
30 Signals::from_bits(fcomp::SIGNAL_DISPLAY_NOT_OWNED).expect("static init should not fail")
31});
32
33static ANY_DISPLAY_EVENT: LazyLock<Signals> = LazyLock::new(|| *DISPLAY_OWNED | *DISPLAY_UNOWNED);
35
36#[derive(Debug, Clone, PartialEq)]
38struct Ownership {
39 signals: Signals,
40}
41
42impl std::convert::From<Signals> for Ownership {
43 fn from(signals: Signals) -> Self {
44 Ownership { signals }
45 }
46}
47
48impl Ownership {
49 fn is_display_ownership_lost(&self) -> bool {
52 self.signals.contains(*DISPLAY_UNOWNED)
53 }
54
55 fn next_signal(&self) -> Signals {
59 match self.is_display_ownership_lost() {
60 true => *DISPLAY_OWNED,
61 false => *DISPLAY_UNOWNED,
62 }
63 }
64
65 async fn wait_ownership_change<'a, T: AsHandleRef>(
70 &self,
71 event: &'a T,
72 ) -> Result<Signals, Status> {
73 OnSignals::new(event, self.next_signal()).await
74 }
75}
76
77pub struct DisplayOwnership {
85 ownership: Rc<RefCell<Ownership>>,
88
89 key_state: RefCell<KeyState>,
91
92 display_ownership_change_receiver: RefCell<UnboundedReceiver<Ownership>>,
94
95 _display_ownership_task: Task<()>,
98
99 inspect_status: InputHandlerStatus,
101
102 #[cfg(test)]
108 loop_done: RefCell<Option<UnboundedSender<()>>>,
109}
110
111impl DisplayOwnership {
112 pub fn new(
119 display_ownership_event: impl AsHandleRef + 'static,
120 input_handlers_node: &fuchsia_inspect::Node,
121 ) -> Rc<Self> {
122 DisplayOwnership::new_internal(display_ownership_event, None, input_handlers_node)
123 }
124
125 #[cfg(test)]
126 pub fn new_for_test(
127 display_ownership_event: impl AsHandleRef + 'static,
128 loop_done: UnboundedSender<()>,
129 ) -> Rc<Self> {
130 let inspector = fuchsia_inspect::Inspector::default();
131 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
132 DisplayOwnership::new_internal(
133 display_ownership_event,
134 Some(loop_done),
135 &fake_handlers_node,
136 )
137 }
138
139 fn new_internal(
140 display_ownership_event: impl AsHandleRef + 'static,
141 _loop_done: Option<UnboundedSender<()>>,
142 input_handlers_node: &fuchsia_inspect::Node,
143 ) -> Rc<Self> {
144 let initial_state = display_ownership_event
145 .wait_handle(*ANY_DISPLAY_EVENT, MonotonicInstant::INFINITE_PAST)
148 .expect("unable to set the initial display state");
149 log::debug!("setting initial display ownership to: {:?}", &initial_state);
150 let initial_ownership: Ownership = initial_state.into();
151 let ownership = Rc::new(RefCell::new(initial_ownership.clone()));
152
153 let mut ownership_clone = initial_ownership;
154 let (ownership_sender, ownership_receiver) = mpsc::unbounded();
155 let display_ownership_task = Task::local(async move {
156 loop {
157 let signals = ownership_clone.wait_ownership_change(&display_ownership_event).await;
158 match signals {
159 Err(e) => {
160 log::warn!("could not read display state: {:?}", e);
161 break;
162 }
163 Ok(signals) => {
164 log::debug!("setting display ownership to: {:?}", &signals);
165 ownership_sender.unbounded_send(signals.into()).unwrap();
166 ownership_clone = signals.into();
167 }
168 }
169 }
170 log::warn!(
171 "display loop exiting and will no longer monitor display changes - this is not expected"
172 );
173 });
174 log::info!("Display ownership handler installed");
175 let inspect_status = InputHandlerStatus::new(
176 input_handlers_node,
177 "display_ownership",
178 false,
179 );
180 Rc::new(Self {
181 ownership,
182 key_state: RefCell::new(KeyState::new()),
183 display_ownership_change_receiver: RefCell::new(ownership_receiver),
184 _display_ownership_task: display_ownership_task,
185 inspect_status,
186 #[cfg(test)]
187 loop_done: RefCell::new(_loop_done),
188 })
189 }
190
191 fn is_display_ownership_lost(&self) -> bool {
193 self.ownership.borrow().is_display_ownership_lost()
194 }
195
196 pub async fn handle_input_events(
198 self: &Rc<Self>,
199 mut input: UnboundedReceiver<InputEvent>,
200 output: UnboundedSender<InputEvent>,
201 ) -> Result<()> {
202 loop {
203 let mut ownership_source = self.display_ownership_change_receiver.borrow_mut();
204 select! {
205 new_ownership = ownership_source.select_next_some() => {
207 let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
208 let event_type = match is_display_ownership_lost {
212 true => KeyEventType::Cancel,
213 false => KeyEventType::Sync,
214 };
215 let keys = self.key_state.borrow().get_set();
216 let mut event_time = MonotonicInstant::get();
217 for key in keys.into_iter() {
218 let key_event = KeyboardEvent::new(key, event_type);
219 output.unbounded_send(into_input_event(key_event, event_time))
220 .context("unable to send display updates")?;
221 event_time = event_time + MonotonicDuration::from_nanos(1);
222 }
223 *(self.ownership.borrow_mut()) = new_ownership;
224 },
225
226 event = input.select_next_some() => {
228 if event.is_handled() {
229 output.unbounded_send(event).context("unable to send handled event")?;
231 continue;
232 }
233 self.inspect_status.count_received_event(input_device::InputEvent::from(event.clone()));
234 match event.device_event {
235 input_device::InputDeviceEvent::Keyboard(ref e) => {
236 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
237 },
238 _ => {},
239 }
240 let is_display_ownership_lost = self.is_display_ownership_lost();
241 if is_display_ownership_lost {
242 self.inspect_status.count_handled_event();
243 }
244 output.unbounded_send(
245 input_device::InputEvent::from(event)
246 .into_handled_if(is_display_ownership_lost)
247 ).context("unable to send input event updates")?;
248 },
249 };
250 #[cfg(test)]
251 {
252 self.loop_done.borrow_mut().as_ref().unwrap().unbounded_send(()).unwrap();
253 }
254 }
255 }
256
257 pub fn set_handler_healthy(self: std::rc::Rc<Self>) {
258 self.inspect_status.health_node.borrow_mut().set_ok();
259 }
260
261 pub fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
262 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
263 }
264}
265
266fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
267 input_device::InputDeviceDescriptor::Keyboard(
268 KeyboardDeviceDescriptor {
270 keys: vec![],
271 device_information: fidl_fuchsia_input_report::DeviceInformation {
272 vendor_id: Some(0),
273 product_id: Some(0),
274 version: Some(0),
275 polling_rate: Some(0),
276 ..Default::default()
277 },
278 device_id: 0,
279 },
280 )
281}
282
283fn into_input_event(
284 keyboard_event: KeyboardEvent,
285 event_time: MonotonicInstant,
286) -> input_device::InputEvent {
287 input_device::InputEvent {
288 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
289 device_descriptor: empty_keyboard_device_descriptor(),
290 event_time,
291 handled: input_device::Handled::No,
292 trace_id: None,
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299 use crate::testing_utilities::{create_fake_input_event, create_input_event};
300 use fidl_fuchsia_input::Key;
301 use fuchsia_async as fasync;
302 use pretty_assertions::assert_eq;
303 use zx::{EventPair, Peered};
304
305 struct DisplayWrangler {
309 event: EventPair,
310 last: Signals,
311 }
312
313 impl DisplayWrangler {
314 fn new(event: EventPair) -> Self {
315 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
316 instance.set_unowned();
320 instance
321 }
322
323 fn set_unowned(&mut self) {
324 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
325 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
326 self.last = *DISPLAY_UNOWNED;
327 }
328
329 fn set_owned(&mut self) {
330 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
331 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
332 self.last = *DISPLAY_OWNED;
333 }
334 }
335
336 #[fuchsia::test]
337 async fn display_ownership_change() {
338 let (test_event, handler_event) = EventPair::create();
342
343 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
345
346 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
348
349 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
352
353 let mut wrangler = DisplayWrangler::new(test_event);
356 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
357
358 let _task = fasync::Task::local(async move {
359 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
360 });
361
362 let fake_time = MonotonicInstant::from_nanos(42);
363
364 wrangler.set_owned();
368 loop_done.next().await;
369 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
370 loop_done.next().await;
371
372 wrangler.set_unowned();
374 loop_done.next().await;
375 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
376 loop_done.next().await;
377
378 wrangler.set_owned();
380 loop_done.next().await;
381 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
382 loop_done.next().await;
383
384 wrangler.set_unowned();
386 loop_done.next().await;
387 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
388 loop_done.next().await;
389
390 let actual: Vec<InputEvent> =
391 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
392
393 assert_eq!(
394 actual,
395 vec![
396 create_fake_input_event(fake_time),
398 create_fake_input_event(fake_time).into_handled(),
400 create_fake_input_event(fake_time),
402 create_fake_input_event(fake_time).into_handled(),
404 ]
405 );
406 }
407
408 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
409 let fake_time = MonotonicInstant::from_nanos(42);
410 create_input_event(
411 KeyboardEvent::new(key, event_type),
412 &input_device::InputDeviceDescriptor::Fake,
413 fake_time,
414 input_device::Handled::No,
415 )
416 }
417
418 #[fuchsia::test]
419 async fn basic_key_state_handling() {
420 let (test_event, handler_event) = EventPair::create();
421 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
422 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
423 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
424 let mut wrangler = DisplayWrangler::new(test_event);
425 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
426 let _task = fasync::Task::local(async move {
427 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
428 });
429
430 let fake_time = MonotonicInstant::from_nanos(42);
431
432 wrangler.set_owned();
434 loop_done.next().await;
435 test_sender
436 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
437 .unwrap();
438 loop_done.next().await;
439
440 wrangler.set_unowned();
442 loop_done.next().await;
443
444 wrangler.set_owned();
446 loop_done.next().await;
447
448 test_sender
450 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
451 .unwrap();
452 loop_done.next().await;
453
454 let actual: Vec<InputEvent> =
455 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
456
457 assert_eq!(
458 actual,
459 vec![
460 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
461 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
462 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
463 new_keyboard_input_event(Key::A, KeyEventType::Sync)
464 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
465 new_keyboard_input_event(Key::A, KeyEventType::Released),
466 ]
467 );
468 }
469
470 #[fuchsia::test]
471 async fn more_key_state_handling() {
472 let (test_event, handler_event) = EventPair::create();
473 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
474 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
475 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
476 let mut wrangler = DisplayWrangler::new(test_event);
477 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
478 let _task = fasync::Task::local(async move {
479 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
480 });
481
482 let fake_time = MonotonicInstant::from_nanos(42);
483
484 wrangler.set_owned();
485 loop_done.next().await;
486 test_sender
487 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
488 .unwrap();
489 loop_done.next().await;
490 test_sender
491 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
492 .unwrap();
493 loop_done.next().await;
494
495 wrangler.set_unowned();
497 loop_done.next().await;
498 test_sender
499 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
500 .unwrap();
501 loop_done.next().await;
502 test_sender
503 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
504 .unwrap();
505 loop_done.next().await;
506
507 wrangler.set_owned();
509 loop_done.next().await;
510
511 test_sender
513 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
514 .unwrap();
515 loop_done.next().await;
516 test_sender
517 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
518 .unwrap();
519 loop_done.next().await;
520
521 let actual: Vec<InputEvent> =
522 test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;
523
524 assert_eq!(
525 actual,
526 vec![
527 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
528 new_keyboard_input_event(Key::B, KeyEventType::Pressed),
529 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
530 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
531 new_keyboard_input_event(Key::B, KeyEventType::Cancel)
532 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
533 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
534 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
535 new_keyboard_input_event(Key::A, KeyEventType::Sync)
539 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
540 new_keyboard_input_event(Key::C, KeyEventType::Sync)
541 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
542 new_keyboard_input_event(Key::A, KeyEventType::Released),
543 new_keyboard_input_event(Key::C, KeyEventType::Released),
544 ]
545 );
546 }
547
548 #[fuchsia::test]
549 async fn display_ownership_initialized_with_inspect_node() {
550 let (test_event, handler_event) = EventPair::create();
551 let (loop_done_sender, _) = mpsc::unbounded::<()>();
552 let inspector = fuchsia_inspect::Inspector::default();
553 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
554 let _ = DisplayWrangler::new(test_event);
556 let _handler = DisplayOwnership::new_internal(
557 handler_event,
558 Some(loop_done_sender),
559 &fake_handlers_node,
560 );
561 diagnostics_assertions::assert_data_tree!(inspector, root: {
562 input_handlers_node: {
563 display_ownership: {
564 events_received_count: 0u64,
565 events_handled_count: 0u64,
566 last_received_timestamp_ns: 0u64,
567 "fuchsia.inspect.Health": {
568 status: "STARTING_UP",
569 start_timestamp_nanos: diagnostics_assertions::AnyProperty
572 },
573 }
574 }
575 });
576 }
577
578 #[fuchsia::test]
579 async fn display_ownership_inspect_counts_events() {
580 let (test_event, handler_event) = EventPair::create();
581 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
582 let (handler_sender, _test_receiver) = mpsc::unbounded::<InputEvent>();
583 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
584 let mut wrangler = DisplayWrangler::new(test_event);
585 let inspector = fuchsia_inspect::Inspector::default();
586 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
587 let handler = DisplayOwnership::new_internal(
588 handler_event,
589 Some(loop_done_sender),
590 &fake_handlers_node,
591 );
592 let _task = fasync::Task::local(async move {
593 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
594 });
595
596 wrangler.set_owned();
598 loop_done.next().await;
599 test_sender
600 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
601 .unwrap();
602 loop_done.next().await;
603
604 wrangler.set_unowned();
607 loop_done.next().await;
608 test_sender
609 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
610 .unwrap();
611 loop_done.next().await;
612
613 wrangler.set_owned();
615 loop_done.next().await;
616
617 test_sender
619 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
620 .unwrap();
621 loop_done.next().await;
622
623 diagnostics_assertions::assert_data_tree!(inspector, root: {
624 input_handlers_node: {
625 display_ownership: {
626 events_received_count: 3u64,
627 events_handled_count: 1u64,
628 last_received_timestamp_ns: 42u64,
629 "fuchsia.inspect.Health": {
630 status: "STARTING_UP",
631 start_timestamp_nanos: diagnostics_assertions::AnyProperty
634 },
635 }
636 }
637 });
638 }
639}