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 fuchsia_trace::duration!(c"input", c"display_ownership");
229 if event.is_handled() {
230 output.unbounded_send(event).context("unable to send handled event")?;
232 continue;
233 }
234 self.inspect_status.count_received_event(&event.event_time);
235 match event.device_event {
236 input_device::InputDeviceEvent::Keyboard(ref e) => {
237 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
238 },
239 _ => {},
240 }
241 let is_display_ownership_lost = self.is_display_ownership_lost();
242 if is_display_ownership_lost {
243 self.inspect_status.count_handled_event();
244 }
245 output.unbounded_send(
246 input_device::InputEvent::from(event)
247 .into_handled_if(is_display_ownership_lost)
248 ).context("unable to send input event updates")?;
249 },
250 };
251 #[cfg(test)]
252 {
253 self.loop_done.borrow_mut().as_ref().unwrap().unbounded_send(()).unwrap();
254 }
255 }
256 }
257
258 pub fn set_handler_healthy(self: std::rc::Rc<Self>) {
259 self.inspect_status.health_node.borrow_mut().set_ok();
260 }
261
262 pub fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
263 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
264 }
265}
266
267fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
268 input_device::InputDeviceDescriptor::Keyboard(
269 KeyboardDeviceDescriptor {
271 keys: vec![],
272 device_information: fidl_fuchsia_input_report::DeviceInformation {
273 vendor_id: Some(0),
274 product_id: Some(0),
275 version: Some(0),
276 polling_rate: Some(0),
277 ..Default::default()
278 },
279 device_id: 0,
280 },
281 )
282}
283
284fn into_input_event(
285 keyboard_event: KeyboardEvent,
286 event_time: MonotonicInstant,
287) -> input_device::InputEvent {
288 input_device::InputEvent {
289 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
290 device_descriptor: empty_keyboard_device_descriptor(),
291 event_time,
292 handled: input_device::Handled::No,
293 trace_id: None,
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300 use crate::testing_utilities::{create_fake_input_event, create_input_event};
301 use fidl_fuchsia_input::Key;
302 use fuchsia_async as fasync;
303 use pretty_assertions::assert_eq;
304 use zx::{EventPair, Peered};
305
306 struct DisplayWrangler {
310 event: EventPair,
311 last: Signals,
312 }
313
314 impl DisplayWrangler {
315 fn new(event: EventPair) -> Self {
316 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
317 instance.set_unowned();
321 instance
322 }
323
324 fn set_unowned(&mut self) {
325 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
326 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
327 self.last = *DISPLAY_UNOWNED;
328 }
329
330 fn set_owned(&mut self) {
331 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
332 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
333 self.last = *DISPLAY_OWNED;
334 }
335 }
336
337 #[fuchsia::test]
338 async fn display_ownership_change() {
339 let (test_event, handler_event) = EventPair::create();
343
344 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
346
347 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
349
350 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
353
354 let mut wrangler = DisplayWrangler::new(test_event);
357 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
358
359 let _task = fasync::Task::local(async move {
360 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
361 });
362
363 let fake_time = MonotonicInstant::from_nanos(42);
364
365 wrangler.set_owned();
369 loop_done.next().await;
370 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
371 loop_done.next().await;
372
373 wrangler.set_unowned();
375 loop_done.next().await;
376 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
377 loop_done.next().await;
378
379 wrangler.set_owned();
381 loop_done.next().await;
382 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
383 loop_done.next().await;
384
385 wrangler.set_unowned();
387 loop_done.next().await;
388 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
389 loop_done.next().await;
390
391 let actual: Vec<InputEvent> =
392 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
393
394 assert_eq!(
395 actual,
396 vec![
397 create_fake_input_event(fake_time),
399 create_fake_input_event(fake_time).into_handled(),
401 create_fake_input_event(fake_time),
403 create_fake_input_event(fake_time).into_handled(),
405 ]
406 );
407 }
408
409 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
410 let fake_time = MonotonicInstant::from_nanos(42);
411 create_input_event(
412 KeyboardEvent::new(key, event_type),
413 &input_device::InputDeviceDescriptor::Fake,
414 fake_time,
415 input_device::Handled::No,
416 )
417 }
418
419 #[fuchsia::test]
420 async fn basic_key_state_handling() {
421 let (test_event, handler_event) = EventPair::create();
422 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
423 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
424 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
425 let mut wrangler = DisplayWrangler::new(test_event);
426 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
427 let _task = fasync::Task::local(async move {
428 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
429 });
430
431 let fake_time = MonotonicInstant::from_nanos(42);
432
433 wrangler.set_owned();
435 loop_done.next().await;
436 test_sender
437 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
438 .unwrap();
439 loop_done.next().await;
440
441 wrangler.set_unowned();
443 loop_done.next().await;
444
445 wrangler.set_owned();
447 loop_done.next().await;
448
449 test_sender
451 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
452 .unwrap();
453 loop_done.next().await;
454
455 let actual: Vec<InputEvent> =
456 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
457
458 assert_eq!(
459 actual,
460 vec![
461 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
462 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
463 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
464 new_keyboard_input_event(Key::A, KeyEventType::Sync)
465 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
466 new_keyboard_input_event(Key::A, KeyEventType::Released),
467 ]
468 );
469 }
470
471 #[fuchsia::test]
472 async fn more_key_state_handling() {
473 let (test_event, handler_event) = EventPair::create();
474 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
475 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
476 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
477 let mut wrangler = DisplayWrangler::new(test_event);
478 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
479 let _task = fasync::Task::local(async move {
480 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
481 });
482
483 let fake_time = MonotonicInstant::from_nanos(42);
484
485 wrangler.set_owned();
486 loop_done.next().await;
487 test_sender
488 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
489 .unwrap();
490 loop_done.next().await;
491 test_sender
492 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
493 .unwrap();
494 loop_done.next().await;
495
496 wrangler.set_unowned();
498 loop_done.next().await;
499 test_sender
500 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
501 .unwrap();
502 loop_done.next().await;
503 test_sender
504 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
505 .unwrap();
506 loop_done.next().await;
507
508 wrangler.set_owned();
510 loop_done.next().await;
511
512 test_sender
514 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
515 .unwrap();
516 loop_done.next().await;
517 test_sender
518 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
519 .unwrap();
520 loop_done.next().await;
521
522 let actual: Vec<InputEvent> =
523 test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;
524
525 assert_eq!(
526 actual,
527 vec![
528 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
529 new_keyboard_input_event(Key::B, KeyEventType::Pressed),
530 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
531 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
532 new_keyboard_input_event(Key::B, KeyEventType::Cancel)
533 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
534 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
535 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
536 new_keyboard_input_event(Key::A, KeyEventType::Sync)
540 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
541 new_keyboard_input_event(Key::C, KeyEventType::Sync)
542 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
543 new_keyboard_input_event(Key::A, KeyEventType::Released),
544 new_keyboard_input_event(Key::C, KeyEventType::Released),
545 ]
546 );
547 }
548
549 #[fuchsia::test]
550 async fn display_ownership_initialized_with_inspect_node() {
551 let (test_event, handler_event) = EventPair::create();
552 let (loop_done_sender, _) = mpsc::unbounded::<()>();
553 let inspector = fuchsia_inspect::Inspector::default();
554 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
555 let _ = DisplayWrangler::new(test_event);
557 let _handler = DisplayOwnership::new_internal(
558 handler_event,
559 Some(loop_done_sender),
560 &fake_handlers_node,
561 );
562 diagnostics_assertions::assert_data_tree!(inspector, root: {
563 input_handlers_node: {
564 display_ownership: {
565 events_received_count: 0u64,
566 events_handled_count: 0u64,
567 last_received_timestamp_ns: 0u64,
568 "fuchsia.inspect.Health": {
569 status: "STARTING_UP",
570 start_timestamp_nanos: diagnostics_assertions::AnyProperty
573 },
574 }
575 }
576 });
577 }
578
579 #[fuchsia::test]
580 async fn display_ownership_inspect_counts_events() {
581 let (test_event, handler_event) = EventPair::create();
582 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
583 let (handler_sender, _test_receiver) = mpsc::unbounded::<InputEvent>();
584 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
585 let mut wrangler = DisplayWrangler::new(test_event);
586 let inspector = fuchsia_inspect::Inspector::default();
587 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
588 let handler = DisplayOwnership::new_internal(
589 handler_event,
590 Some(loop_done_sender),
591 &fake_handlers_node,
592 );
593 let _task = fasync::Task::local(async move {
594 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
595 });
596
597 wrangler.set_owned();
599 loop_done.next().await;
600 test_sender
601 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
602 .unwrap();
603 loop_done.next().await;
604
605 wrangler.set_unowned();
608 loop_done.next().await;
609 test_sender
610 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
611 .unwrap();
612 loop_done.next().await;
613
614 wrangler.set_owned();
616 loop_done.next().await;
617
618 test_sender
620 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
621 .unwrap();
622 loop_done.next().await;
623
624 diagnostics_assertions::assert_data_tree!(inspector, root: {
625 input_handlers_node: {
626 display_ownership: {
627 events_received_count: 3u64,
628 events_handled_count: 1u64,
629 last_received_timestamp_ns: 42u64,
630 "fuchsia.inspect.Health": {
631 status: "STARTING_UP",
632 start_timestamp_nanos: diagnostics_assertions::AnyProperty
635 },
636 }
637 }
638 });
639 }
640}