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::{select, StreamExt};
15use keymaps::KeyState;
16use lazy_static::lazy_static;
17use std::cell::RefCell;
18use std::rc::Rc;
19use zx::{AsHandleRef, MonotonicDuration, MonotonicInstant, Signals, Status};
20
21lazy_static! {
22 static ref DISPLAY_OWNED: Signals = Signals::from_bits(fcomp::SIGNAL_DISPLAY_OWNED)
25 .expect("static init should not fail") ;
26
27 static ref DISPLAY_UNOWNED: Signals = Signals::from_bits(fcomp::SIGNAL_DISPLAY_NOT_OWNED)
30 .expect("static init should not fail") ;
31
32 static ref ANY_DISPLAY_EVENT: Signals = *DISPLAY_OWNED | *DISPLAY_UNOWNED;
34}
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!("display loop exiting and will no longer monitor display changes - this is not expected");
171 });
172 log::info!("Display ownership handler installed");
173 let inspect_status = InputHandlerStatus::new(
174 input_handlers_node,
175 "display_ownership",
176 false,
177 );
178 Rc::new(Self {
179 ownership,
180 key_state: RefCell::new(KeyState::new()),
181 display_ownership_change_receiver: RefCell::new(ownership_receiver),
182 _display_ownership_task: display_ownership_task,
183 inspect_status,
184 #[cfg(test)]
185 loop_done: RefCell::new(_loop_done),
186 })
187 }
188
189 fn is_display_ownership_lost(&self) -> bool {
191 self.ownership.borrow().is_display_ownership_lost()
192 }
193
194 pub async fn handle_input_events(
196 self: &Rc<Self>,
197 mut input: UnboundedReceiver<InputEvent>,
198 output: UnboundedSender<InputEvent>,
199 ) -> Result<()> {
200 loop {
201 let mut ownership_source = self.display_ownership_change_receiver.borrow_mut();
202 select! {
203 new_ownership = ownership_source.select_next_some() => {
205 let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
206 let event_type = match is_display_ownership_lost {
210 true => KeyEventType::Cancel,
211 false => KeyEventType::Sync,
212 };
213 let keys = self.key_state.borrow().get_set();
214 let mut event_time = MonotonicInstant::get();
215 for key in keys.into_iter() {
216 let key_event = KeyboardEvent::new(key, event_type);
217 output.unbounded_send(into_input_event(key_event, event_time))
218 .context("unable to send display updates")?;
219 event_time = event_time + MonotonicDuration::from_nanos(1);
220 }
221 *(self.ownership.borrow_mut()) = new_ownership;
222 },
223
224 event = input.select_next_some() => {
226 if event.is_handled() {
227 output.unbounded_send(event).context("unable to send handled event")?;
229 continue;
230 }
231 self.inspect_status.count_received_event(input_device::InputEvent::from(event.clone()));
232 match event.device_event {
233 input_device::InputDeviceEvent::Keyboard(ref e) => {
234 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
235 },
236 _ => {},
237 }
238 let is_display_ownership_lost = self.is_display_ownership_lost();
239 if is_display_ownership_lost {
240 self.inspect_status.count_handled_event();
241 }
242 output.unbounded_send(
243 input_device::InputEvent::from(event)
244 .into_handled_if(is_display_ownership_lost)
245 ).context("unable to send input event updates")?;
246 },
247 };
248 #[cfg(test)]
249 {
250 self.loop_done.borrow_mut().as_ref().unwrap().unbounded_send(()).unwrap();
251 }
252 }
253 }
254
255 pub fn set_handler_healthy(self: std::rc::Rc<Self>) {
256 self.inspect_status.health_node.borrow_mut().set_ok();
257 }
258
259 pub fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
260 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
261 }
262}
263
264fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
265 input_device::InputDeviceDescriptor::Keyboard(
266 KeyboardDeviceDescriptor {
268 keys: vec![],
269 device_information: fidl_fuchsia_input_report::DeviceInformation {
270 vendor_id: Some(0),
271 product_id: Some(0),
272 version: Some(0),
273 polling_rate: Some(0),
274 ..Default::default()
275 },
276 device_id: 0,
277 },
278 )
279}
280
281fn into_input_event(
282 keyboard_event: KeyboardEvent,
283 event_time: MonotonicInstant,
284) -> input_device::InputEvent {
285 input_device::InputEvent {
286 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
287 device_descriptor: empty_keyboard_device_descriptor(),
288 event_time,
289 handled: input_device::Handled::No,
290 trace_id: None,
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297 use crate::testing_utilities::{create_fake_input_event, create_input_event};
298 use fidl_fuchsia_input::Key;
299 use fuchsia_async as fasync;
300 use pretty_assertions::assert_eq;
301 use zx::{EventPair, Peered};
302
303 struct DisplayWrangler {
307 event: EventPair,
308 last: Signals,
309 }
310
311 impl DisplayWrangler {
312 fn new(event: EventPair) -> Self {
313 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
314 instance.set_unowned();
318 instance
319 }
320
321 fn set_unowned(&mut self) {
322 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
323 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
324 self.last = *DISPLAY_UNOWNED;
325 }
326
327 fn set_owned(&mut self) {
328 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
329 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
330 self.last = *DISPLAY_OWNED;
331 }
332 }
333
334 #[fuchsia::test]
335 async fn display_ownership_change() {
336 let (test_event, handler_event) = EventPair::create();
340
341 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
343
344 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
346
347 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
350
351 let mut wrangler = DisplayWrangler::new(test_event);
354 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
355
356 let _task = fasync::Task::local(async move {
357 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
358 });
359
360 let fake_time = MonotonicInstant::from_nanos(42);
361
362 wrangler.set_owned();
366 loop_done.next().await;
367 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
368 loop_done.next().await;
369
370 wrangler.set_unowned();
372 loop_done.next().await;
373 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
374 loop_done.next().await;
375
376 wrangler.set_owned();
378 loop_done.next().await;
379 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
380 loop_done.next().await;
381
382 wrangler.set_unowned();
384 loop_done.next().await;
385 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
386 loop_done.next().await;
387
388 let actual: Vec<InputEvent> =
389 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
390
391 assert_eq!(
392 actual,
393 vec![
394 create_fake_input_event(fake_time),
396 create_fake_input_event(fake_time).into_handled(),
398 create_fake_input_event(fake_time),
400 create_fake_input_event(fake_time).into_handled(),
402 ]
403 );
404 }
405
406 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
407 let fake_time = MonotonicInstant::from_nanos(42);
408 create_input_event(
409 KeyboardEvent::new(key, event_type),
410 &input_device::InputDeviceDescriptor::Fake,
411 fake_time,
412 input_device::Handled::No,
413 )
414 }
415
416 #[fuchsia::test]
417 async fn basic_key_state_handling() {
418 let (test_event, handler_event) = EventPair::create();
419 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
420 let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
421 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
422 let mut wrangler = DisplayWrangler::new(test_event);
423 let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
424 let _task = fasync::Task::local(async move {
425 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
426 });
427
428 let fake_time = MonotonicInstant::from_nanos(42);
429
430 wrangler.set_owned();
432 loop_done.next().await;
433 test_sender
434 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
435 .unwrap();
436 loop_done.next().await;
437
438 wrangler.set_unowned();
440 loop_done.next().await;
441
442 wrangler.set_owned();
444 loop_done.next().await;
445
446 test_sender
448 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
449 .unwrap();
450 loop_done.next().await;
451
452 let actual: Vec<InputEvent> =
453 test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;
454
455 assert_eq!(
456 actual,
457 vec![
458 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
459 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
460 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
461 new_keyboard_input_event(Key::A, KeyEventType::Sync)
462 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
463 new_keyboard_input_event(Key::A, KeyEventType::Released),
464 ]
465 );
466 }
467
468 #[fuchsia::test]
469 async fn more_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 let _task = fasync::Task::local(async move {
477 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
478 });
479
480 let fake_time = MonotonicInstant::from_nanos(42);
481
482 wrangler.set_owned();
483 loop_done.next().await;
484 test_sender
485 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
486 .unwrap();
487 loop_done.next().await;
488 test_sender
489 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
490 .unwrap();
491 loop_done.next().await;
492
493 wrangler.set_unowned();
495 loop_done.next().await;
496 test_sender
497 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
498 .unwrap();
499 loop_done.next().await;
500 test_sender
501 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
502 .unwrap();
503 loop_done.next().await;
504
505 wrangler.set_owned();
507 loop_done.next().await;
508
509 test_sender
511 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
512 .unwrap();
513 loop_done.next().await;
514 test_sender
515 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
516 .unwrap();
517 loop_done.next().await;
518
519 let actual: Vec<InputEvent> =
520 test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;
521
522 assert_eq!(
523 actual,
524 vec![
525 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
526 new_keyboard_input_event(Key::B, 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::B, KeyEventType::Cancel)
530 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
531 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
532 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
533 new_keyboard_input_event(Key::A, KeyEventType::Sync)
537 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
538 new_keyboard_input_event(Key::C, KeyEventType::Sync)
539 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
540 new_keyboard_input_event(Key::A, KeyEventType::Released),
541 new_keyboard_input_event(Key::C, KeyEventType::Released),
542 ]
543 );
544 }
545
546 #[fuchsia::test]
547 async fn display_ownership_initialized_with_inspect_node() {
548 let (test_event, handler_event) = EventPair::create();
549 let (loop_done_sender, _) = mpsc::unbounded::<()>();
550 let inspector = fuchsia_inspect::Inspector::default();
551 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
552 let _ = DisplayWrangler::new(test_event);
554 let _handler = DisplayOwnership::new_internal(
555 handler_event,
556 Some(loop_done_sender),
557 &fake_handlers_node,
558 );
559 diagnostics_assertions::assert_data_tree!(inspector, root: {
560 input_handlers_node: {
561 display_ownership: {
562 events_received_count: 0u64,
563 events_handled_count: 0u64,
564 last_received_timestamp_ns: 0u64,
565 "fuchsia.inspect.Health": {
566 status: "STARTING_UP",
567 start_timestamp_nanos: diagnostics_assertions::AnyProperty
570 },
571 }
572 }
573 });
574 }
575
576 #[fuchsia::test]
577 async fn display_ownership_inspect_counts_events() {
578 let (test_event, handler_event) = EventPair::create();
579 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
580 let (handler_sender, _test_receiver) = mpsc::unbounded::<InputEvent>();
581 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
582 let mut wrangler = DisplayWrangler::new(test_event);
583 let inspector = fuchsia_inspect::Inspector::default();
584 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
585 let handler = DisplayOwnership::new_internal(
586 handler_event,
587 Some(loop_done_sender),
588 &fake_handlers_node,
589 );
590 let _task = fasync::Task::local(async move {
591 handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
592 });
593
594 wrangler.set_owned();
596 loop_done.next().await;
597 test_sender
598 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
599 .unwrap();
600 loop_done.next().await;
601
602 wrangler.set_unowned();
605 loop_done.next().await;
606 test_sender
607 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
608 .unwrap();
609 loop_done.next().await;
610
611 wrangler.set_owned();
613 loop_done.next().await;
614
615 test_sender
617 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
618 .unwrap();
619 loop_done.next().await;
620
621 diagnostics_assertions::assert_data_tree!(inspector, root: {
622 input_handlers_node: {
623 display_ownership: {
624 events_received_count: 3u64,
625 events_handled_count: 1u64,
626 last_received_timestamp_ns: 42u64,
627 "fuchsia.inspect.Health": {
628 status: "STARTING_UP",
629 start_timestamp_nanos: diagnostics_assertions::AnyProperty
632 },
633 }
634 }
635 });
636 }
637}