1use crate::input_device::{self, InputEvent, UnhandledInputEvent};
6use crate::input_handler::{Handler, InputHandlerStatus, UnhandledInputHandler};
7use crate::keyboard_binding::{KeyboardDeviceDescriptor, KeyboardEvent};
8use crate::metrics;
9use anyhow::{Context, Result};
10use async_trait::async_trait;
11use fidl_fuchsia_ui_composition_internal as fcomp;
12use fidl_fuchsia_ui_input3::KeyEventType;
13use fuchsia_async::{OnSignals, Task};
14use fuchsia_inspect::health::Reporter;
15use futures::StreamExt;
16use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
17use keymaps::KeyState;
18use metrics_registry::InputPipelineErrorMetricDimensionEvent;
19use std::cell::RefCell;
20use std::rc::Rc;
21use std::sync::LazyLock;
22use zx::{
23 AsHandleRef, MonotonicDuration, MonotonicInstant, NullableHandle, Rights, Signals, Status,
24 WaitResult,
25};
26
27static DISPLAY_OWNED: LazyLock<Signals> = LazyLock::new(|| {
30 Signals::from_bits(fcomp::SIGNAL_DISPLAY_OWNED).expect("static init should not fail")
31});
32
33static DISPLAY_UNOWNED: LazyLock<Signals> = LazyLock::new(|| {
36 Signals::from_bits(fcomp::SIGNAL_DISPLAY_NOT_OWNED).expect("static init should not fail")
37});
38
39static ANY_DISPLAY_EVENT: LazyLock<Signals> = LazyLock::new(|| *DISPLAY_OWNED | *DISPLAY_UNOWNED);
41
42#[derive(Debug, Clone, PartialEq)]
44struct Ownership {
45 signals: Signals,
46}
47
48impl std::convert::From<Signals> for Ownership {
49 fn from(signals: Signals) -> Self {
50 Ownership { signals }
51 }
52}
53
54impl Ownership {
55 fn is_display_ownership_lost(&self) -> bool {
58 self.signals.contains(*DISPLAY_UNOWNED)
59 }
60
61 fn next_signal(&self) -> Signals {
65 match self.is_display_ownership_lost() {
66 true => *DISPLAY_OWNED,
67 false => *DISPLAY_UNOWNED,
68 }
69 }
70
71 async fn wait_ownership_change<'a, T: AsHandleRef>(
76 &self,
77 event: &'a T,
78 ) -> Result<Signals, Status> {
79 OnSignals::new(event, self.next_signal()).await
80 }
81}
82
83pub struct DisplayOwnership {
103 ownership: Rc<RefCell<Ownership>>,
106
107 key_state: RefCell<KeyState>,
109
110 display_ownership_change_receiver: RefCell<Option<UnboundedReceiver<Ownership>>>,
112
113 _display_ownership_task: Task<()>,
116
117 metrics_logger: metrics::MetricsLogger,
119
120 inspect_status: InputHandlerStatus,
122
123 #[cfg(test)]
129 loop_done: RefCell<Option<UnboundedSender<()>>>,
130 display_ownership_event: NullableHandle,
131}
132
133impl DisplayOwnership {
134 pub fn new(
141 display_ownership_event: impl AsHandleRef + 'static,
142 input_handlers_node: &fuchsia_inspect::Node,
143 metrics_logger: metrics::MetricsLogger,
144 ) -> Rc<Self> {
145 DisplayOwnership::new_internal(
146 display_ownership_event,
147 None,
148 input_handlers_node,
149 metrics_logger,
150 )
151 }
152
153 #[cfg(test)]
154 pub fn new_for_test(
155 display_ownership_event: impl AsHandleRef + 'static,
156 loop_done: UnboundedSender<()>,
157 metrics_logger: metrics::MetricsLogger,
158 ) -> Rc<Self> {
159 let inspector = fuchsia_inspect::Inspector::default();
160 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
161 DisplayOwnership::new_internal(
162 display_ownership_event,
163 Some(loop_done),
164 &fake_handlers_node,
165 metrics_logger,
166 )
167 }
168
169 fn new_internal(
170 display_ownership_event: impl AsHandleRef + 'static,
171 _loop_done: Option<UnboundedSender<()>>,
172 input_handlers_node: &fuchsia_inspect::Node,
173 metrics_logger: metrics::MetricsLogger,
174 ) -> Rc<Self> {
175 let event_handle = display_ownership_event
176 .as_handle_ref()
177 .duplicate_handle(Rights::SAME_RIGHTS)
178 .expect("unable to duplicate display ownership event");
179 let initial_state = display_ownership_event
180 .as_handle_ref()
183 .wait_one(*ANY_DISPLAY_EVENT, MonotonicInstant::INFINITE_PAST)
184 .expect("unable to set the initial display state");
185 log::debug!("setting initial display ownership to: {:?}", initial_state);
186 let initial_ownership: Ownership = initial_state.into();
187 let ownership = Rc::new(RefCell::new(initial_ownership.clone()));
188
189 let mut ownership_clone = initial_ownership;
190 let (ownership_sender, ownership_receiver) = mpsc::unbounded();
191 let display_ownership_task = Task::local(async move {
192 loop {
193 let signals = ownership_clone.wait_ownership_change(&display_ownership_event).await;
194 match signals {
195 Err(e) => {
196 log::warn!("could not read display state: {:?}", e);
197 break;
198 }
199 Ok(signals) => {
200 log::debug!("setting display ownership to: {:?}", signals);
201 ownership_sender.unbounded_send(signals.into()).unwrap();
202 ownership_clone = signals.into();
203 }
204 }
205 }
206 log::warn!(
207 "display loop exiting and will no longer monitor display changes - this is not expected"
208 );
209 });
210 log::info!("Display ownership handler installed");
211 let inspect_status = InputHandlerStatus::new(
212 input_handlers_node,
213 "display_ownership",
214 false,
215 );
216 Rc::new(Self {
217 ownership,
218 key_state: RefCell::new(KeyState::new()),
219 display_ownership_change_receiver: RefCell::new(Some(ownership_receiver)),
220 _display_ownership_task: display_ownership_task,
221 metrics_logger,
222 inspect_status,
223 #[cfg(test)]
224 loop_done: RefCell::new(_loop_done),
225 display_ownership_event: event_handle,
226 })
227 }
228
229 fn is_display_ownership_lost(&self) -> bool {
231 match self
236 .display_ownership_event
237 .wait_one(*ANY_DISPLAY_EVENT, MonotonicInstant::INFINITE_PAST)
238 {
239 WaitResult::Ok(signals) | WaitResult::TimedOut(signals) => {
240 if signals.contains(Signals::OBJECT_PEER_CLOSED) {
241 true
242 } else {
243 signals.contains(*DISPLAY_UNOWNED)
244 }
245 }
246 WaitResult::Err(Status::PEER_CLOSED) => {
247 true
249 }
250 WaitResult::Canceled(_) => {
251 true
253 }
254 WaitResult::Err(e) => {
255 log::error!("Unexpected error on display ownership event: {:?}", e);
256 self.ownership.borrow().is_display_ownership_lost()
257 }
258 }
259 }
260
261 pub async fn handle_ownership_change(
268 self: &Rc<Self>,
269 output: UnboundedSender<Vec<InputEvent>>,
270 ) -> Result<()> {
271 let mut ownership_source = self
272 .display_ownership_change_receiver
273 .borrow_mut()
274 .take()
275 .context("display_ownership_change_receiver already taken")?;
276 while let Some(new_ownership) = ownership_source.next().await {
277 let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
278 let event_type = match is_display_ownership_lost {
282 true => KeyEventType::Cancel,
283 false => KeyEventType::Sync,
284 };
285 let keys = self.key_state.borrow().get_set();
286 let mut event_time = MonotonicInstant::get();
287 for key in keys.into_iter() {
288 let key_event = KeyboardEvent::new(key, event_type);
289 output
290 .unbounded_send(vec![into_input_event(key_event, event_time)])
291 .context("unable to send display updates")?;
292 event_time = event_time + MonotonicDuration::from_nanos(1);
293 }
294 *(self.ownership.borrow_mut()) = new_ownership;
295 #[cfg(test)]
296 {
297 if let Some(loop_done) = self.loop_done.borrow().as_ref() {
298 loop_done.unbounded_send(()).unwrap();
299 }
300 }
301 }
302 Ok(())
303 }
304}
305
306impl Handler for DisplayOwnership {
307 fn set_handler_healthy(self: std::rc::Rc<Self>) {
308 self.inspect_status.health_node.borrow_mut().set_ok();
309 }
310
311 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
312 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
313 }
314
315 fn get_name(&self) -> &'static str {
316 "DisplayOwnership"
317 }
318
319 fn interest(&self) -> Vec<input_device::InputEventType> {
320 vec![input_device::InputEventType::Keyboard]
321 }
322}
323
324#[async_trait(?Send)]
325impl UnhandledInputHandler for DisplayOwnership {
326 async fn handle_unhandled_input_event(
327 self: Rc<Self>,
328 unhandled_input_event: UnhandledInputEvent,
329 ) -> Vec<input_device::InputEvent> {
330 fuchsia_trace::duration!("input", "display_ownership");
331 self.inspect_status.count_received_event(&unhandled_input_event.event_time);
332 match unhandled_input_event.device_event {
333 input_device::InputDeviceEvent::Keyboard(ref e) => {
334 self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
335 }
336 _ => {
337 self.metrics_logger.log_error(
338 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
339 std::format!(
340 "{} uninterested input event: {:?}",
341 self.get_name(),
342 unhandled_input_event.get_event_type()
343 ),
344 );
345 }
346 }
347 let is_display_ownership_lost = self.is_display_ownership_lost();
348 if is_display_ownership_lost {
349 self.inspect_status.count_handled_event();
350 }
351
352 #[cfg(test)]
353 {
354 if let Some(loop_done) = self.loop_done.borrow().as_ref() {
355 loop_done.unbounded_send(()).unwrap();
356 }
357 }
358
359 vec![
360 input_device::InputEvent::from(unhandled_input_event)
361 .into_handled_if(is_display_ownership_lost),
362 ]
363 }
364}
365
366fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
367 input_device::InputDeviceDescriptor::Keyboard(
368 KeyboardDeviceDescriptor {
370 keys: vec![],
371 device_information: fidl_fuchsia_input_report::DeviceInformation {
372 vendor_id: Some(0),
373 product_id: Some(0),
374 version: Some(0),
375 polling_rate: Some(0),
376 ..Default::default()
377 },
378 device_id: 0,
379 },
380 )
381}
382
383fn into_input_event(
384 keyboard_event: KeyboardEvent,
385 event_time: MonotonicInstant,
386) -> input_device::InputEvent {
387 input_device::InputEvent {
388 device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
389 device_descriptor: empty_keyboard_device_descriptor(),
390 event_time,
391 handled: input_device::Handled::No,
392 trace_id: None,
393 }
394}
395
396#[cfg(test)]
397mod tests {
398 use super::*;
399 use crate::testing_utilities::{create_fake_input_event, create_input_event};
400 use fidl_fuchsia_input::Key;
401 use fuchsia_async as fasync;
402 use pretty_assertions::assert_eq;
403 use std::convert::TryFrom as _;
404 use zx::{EventPair, Peered};
405
406 struct DisplayWrangler {
410 event: EventPair,
411 last: Signals,
412 }
413
414 impl DisplayWrangler {
415 fn new(event: EventPair) -> Self {
416 let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
417 instance.set_unowned();
421 instance
422 }
423
424 fn set_unowned(&mut self) {
425 assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
426 self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
427 self.last = *DISPLAY_UNOWNED;
428 }
429
430 fn set_owned(&mut self) {
431 assert!(self.last != *DISPLAY_OWNED, "display is already owned");
432 self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
433 self.last = *DISPLAY_OWNED;
434 }
435 }
436
437 #[fuchsia::test]
438 async fn display_ownership_change() {
439 let (test_event, handler_event) = EventPair::create();
443
444 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
446
447 let (handler_sender, test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
449
450 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
453
454 let mut wrangler = DisplayWrangler::new(test_event);
457 let handler = DisplayOwnership::new_for_test(
458 handler_event,
459 loop_done_sender,
460 metrics::MetricsLogger::default(),
461 );
462
463 let handler_clone = handler.clone();
464 let handler_sender_clone = handler_sender.clone();
465 let _task = fasync::Task::local(async move {
466 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
467 });
468
469 let handler_clone_2 = handler.clone();
470 let _input_task = fasync::Task::local(async move {
471 let mut receiver = handler_receiver;
472 while let Some(event) = receiver.next().await {
473 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
474 let out_events =
475 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
476 handler_sender.unbounded_send(out_events).unwrap();
477 }
478 });
479
480 let fake_time = MonotonicInstant::from_nanos(42);
481
482 wrangler.set_owned();
486 loop_done.next().await;
487 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
488 loop_done.next().await;
489
490 wrangler.set_unowned();
492 loop_done.next().await;
493 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
494 loop_done.next().await;
495
496 wrangler.set_owned();
498 loop_done.next().await;
499 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
500 loop_done.next().await;
501
502 wrangler.set_unowned();
504 loop_done.next().await;
505 test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
506 loop_done.next().await;
507
508 let actual: Vec<InputEvent> = test_receiver
509 .take(4)
510 .flat_map(|events| futures::stream::iter(events))
511 .map(|e| e.into_with_event_time(fake_time))
512 .collect()
513 .await;
514
515 assert_eq!(
516 actual,
517 vec![
518 create_fake_input_event(fake_time),
520 create_fake_input_event(fake_time).into_handled(),
522 create_fake_input_event(fake_time),
524 create_fake_input_event(fake_time).into_handled(),
526 ]
527 );
528 }
529
530 fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
531 let fake_time = MonotonicInstant::from_nanos(42);
532 create_input_event(
533 KeyboardEvent::new(key, event_type),
534 &input_device::InputDeviceDescriptor::Fake,
535 fake_time,
536 input_device::Handled::No,
537 )
538 }
539
540 #[fuchsia::test]
541 async fn basic_key_state_handling() {
542 let (test_event, handler_event) = EventPair::create();
543 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
544 let (handler_sender, test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
545 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
546 let mut wrangler = DisplayWrangler::new(test_event);
547 let handler = DisplayOwnership::new_for_test(
548 handler_event,
549 loop_done_sender,
550 metrics::MetricsLogger::default(),
551 );
552
553 let handler_clone = handler.clone();
554 let handler_sender_clone = handler_sender.clone();
555 let _task = fasync::Task::local(async move {
556 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
557 });
558
559 let handler_clone_2 = handler.clone();
560 let _input_task = fasync::Task::local(async move {
561 let mut receiver = handler_receiver;
562 while let Some(event) = receiver.next().await {
563 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
564 let out_events =
565 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
566 handler_sender.unbounded_send(out_events).unwrap();
567 }
568 });
569
570 let fake_time = MonotonicInstant::from_nanos(42);
571
572 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
580 wrangler.set_unowned();
582 loop_done.next().await;
583
584 wrangler.set_owned();
586 loop_done.next().await;
587
588 test_sender
590 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
591 .unwrap();
592 loop_done.next().await;
593
594 let actual: Vec<InputEvent> = test_receiver
595 .take(4)
596 .flat_map(|events| futures::stream::iter(events))
597 .map(|e| e.into_with_event_time(fake_time))
598 .collect()
599 .await;
600
601 assert_eq!(
602 actual,
603 vec![
604 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
605 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
606 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
607 new_keyboard_input_event(Key::A, KeyEventType::Sync)
608 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
609 new_keyboard_input_event(Key::A, KeyEventType::Released),
610 ]
611 );
612 }
613
614 #[fuchsia::test]
615 async fn more_key_state_handling() {
616 let (test_event, handler_event) = EventPair::create();
617 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
618 let (handler_sender, test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
619 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
620 let mut wrangler = DisplayWrangler::new(test_event);
621 let handler = DisplayOwnership::new_for_test(
622 handler_event,
623 loop_done_sender,
624 metrics::MetricsLogger::default(),
625 );
626
627 let handler_clone = handler.clone();
628 let handler_sender_clone = handler_sender.clone();
629 let _task = fasync::Task::local(async move {
630 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
631 });
632
633 let handler_clone_2 = handler.clone();
634 let _input_task = fasync::Task::local(async move {
635 let mut receiver = handler_receiver;
636 while let Some(event) = receiver.next().await {
637 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
638 let out_events =
639 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
640 handler_sender.unbounded_send(out_events).unwrap();
641 }
642 });
643
644 let fake_time = MonotonicInstant::from_nanos(42);
645
646 wrangler.set_owned();
647 loop_done.next().await;
648 test_sender
649 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
650 .unwrap();
651 loop_done.next().await;
652 test_sender
653 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
654 .unwrap();
655 loop_done.next().await;
656
657 wrangler.set_unowned();
659 loop_done.next().await;
660 test_sender
661 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
662 .unwrap();
663 loop_done.next().await;
664 test_sender
665 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
666 .unwrap();
667 loop_done.next().await;
668
669 wrangler.set_owned();
671 loop_done.next().await;
672
673 test_sender
675 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
676 .unwrap();
677 loop_done.next().await;
678 test_sender
679 .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
680 .unwrap();
681 loop_done.next().await;
682
683 let actual: Vec<InputEvent> = test_receiver
684 .take(10) .flat_map(|events| futures::stream::iter(events))
686 .map(|e| e.into_with_event_time(fake_time))
687 .collect()
688 .await;
689
690 assert_eq!(
691 actual,
692 vec![
693 new_keyboard_input_event(Key::A, KeyEventType::Pressed),
694 new_keyboard_input_event(Key::B, KeyEventType::Pressed),
695 new_keyboard_input_event(Key::A, KeyEventType::Cancel)
696 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
697 new_keyboard_input_event(Key::B, KeyEventType::Cancel)
698 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
699 new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
700 new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
701 new_keyboard_input_event(Key::A, KeyEventType::Sync)
705 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
706 new_keyboard_input_event(Key::C, KeyEventType::Sync)
707 .into_with_device_descriptor(empty_keyboard_device_descriptor()),
708 new_keyboard_input_event(Key::A, KeyEventType::Released),
709 new_keyboard_input_event(Key::C, KeyEventType::Released),
710 ]
711 );
712 }
713
714 #[fuchsia::test]
715 async fn display_ownership_initialized_with_inspect_node() {
716 let (test_event, handler_event) = EventPair::create();
717 let (loop_done_sender, _) = mpsc::unbounded::<()>();
718 let inspector = fuchsia_inspect::Inspector::default();
719 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
720 let _ = DisplayWrangler::new(test_event);
722 let _handler = DisplayOwnership::new_internal(
723 handler_event,
724 Some(loop_done_sender),
725 &fake_handlers_node,
726 metrics::MetricsLogger::default(),
727 );
728 diagnostics_assertions::assert_data_tree!(inspector, root: {
729 input_handlers_node: {
730 display_ownership: {
731 events_received_count: 0u64,
732 events_handled_count: 0u64,
733 last_received_timestamp_ns: 0u64,
734 "fuchsia.inspect.Health": {
735 status: "STARTING_UP",
736 start_timestamp_nanos: diagnostics_assertions::AnyProperty
739 },
740 }
741 }
742 });
743 }
744
745 #[fuchsia::test]
746 async fn display_ownership_inspect_counts_events() {
747 let (test_event, handler_event) = EventPair::create();
748 let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
749 let (handler_sender, _test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
750 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
751 let mut wrangler = DisplayWrangler::new(test_event);
752 let inspector = fuchsia_inspect::Inspector::default();
753 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
754 let handler = DisplayOwnership::new_internal(
755 handler_event,
756 Some(loop_done_sender),
757 &fake_handlers_node,
758 metrics::MetricsLogger::default(),
759 );
760 let handler_clone = handler.clone();
761 let handler_sender_clone = handler_sender.clone();
762 let _task = fasync::Task::local(async move {
763 handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
764 });
765
766 let handler_clone_2 = handler.clone();
767 let _input_task = fasync::Task::local(async move {
768 let mut receiver = handler_receiver;
769 while let Some(event) = receiver.next().await {
770 let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
771 let out_events =
772 handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
773 handler_sender.unbounded_send(out_events).unwrap();
774 }
775 });
776
777 wrangler.set_owned();
779 loop_done.next().await;
780 test_sender
781 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
782 .unwrap();
783 loop_done.next().await;
784
785 wrangler.set_unowned();
788 loop_done.next().await;
789 test_sender
790 .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
791 .unwrap();
792 loop_done.next().await;
793
794 wrangler.set_owned();
796 loop_done.next().await;
797
798 test_sender
800 .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
801 .unwrap();
802 loop_done.next().await;
803
804 diagnostics_assertions::assert_data_tree!(inspector, root: {
805 input_handlers_node: {
806 display_ownership: {
807 events_received_count: 3u64,
808 events_handled_count: 1u64,
809 last_received_timestamp_ns: 42u64,
810 "fuchsia.inspect.Health": {
811 status: "STARTING_UP",
812 start_timestamp_nanos: diagnostics_assertions::AnyProperty
815 },
816 }
817 }
818 });
819 }
820
821 #[fuchsia::test]
822 async fn display_ownership_peer_closed() {
823 let (test_event, handler_event) = EventPair::create();
824 let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
825
826 let mut wrangler = DisplayWrangler::new(test_event);
827 let handler = DisplayOwnership::new_for_test(
828 handler_event,
829 loop_done_sender,
830 metrics::MetricsLogger::default(),
831 );
832
833 let (handler_sender, _test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
834 let handler_clone = handler.clone();
835 let _task = fasync::Task::local(async move {
836 handler_clone.handle_ownership_change(handler_sender).await.unwrap();
837 });
838
839 wrangler.set_owned();
841 loop_done.next().await;
842
843 assert!(!handler.is_display_ownership_lost());
845
846 std::mem::drop(wrangler);
848
849 assert!(handler.is_display_ownership_lost());
851 }
852}