Skip to main content

input_pipeline_dso/
display_ownership.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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::{AsHandleRef, MonotonicDuration, MonotonicInstant, Signals, Status};
23
24// The signal value corresponding to the `DISPLAY_OWNED_SIGNAL`.  Same as zircon's signal
25// USER_0.
26static DISPLAY_OWNED: LazyLock<Signals> = LazyLock::new(|| {
27    Signals::from_bits(fcomp::SIGNAL_DISPLAY_OWNED).expect("static init should not fail")
28});
29
30// The signal value corresponding to the `DISPLAY_NOT_OWNED_SIGNAL`.  Same as zircon's signal
31// USER_1.
32static DISPLAY_UNOWNED: LazyLock<Signals> = LazyLock::new(|| {
33    Signals::from_bits(fcomp::SIGNAL_DISPLAY_NOT_OWNED).expect("static init should not fail")
34});
35
36// Any display-related signal.
37static ANY_DISPLAY_EVENT: LazyLock<Signals> = LazyLock::new(|| *DISPLAY_OWNED | *DISPLAY_UNOWNED);
38
39// Stores the last received ownership signals.
40#[derive(Debug, Clone, PartialEq)]
41struct Ownership {
42    signals: Signals,
43}
44
45impl std::convert::From<Signals> for Ownership {
46    fn from(signals: Signals) -> Self {
47        Ownership { signals }
48    }
49}
50
51impl Ownership {
52    // Returns true if the display is currently indicated to be not owned by
53    // Scenic.
54    fn is_display_ownership_lost(&self) -> bool {
55        self.signals.contains(*DISPLAY_UNOWNED)
56    }
57
58    // Returns the mask of the next signal to watch.
59    //
60    // Since the ownership alternates, so does the next signal to wait on.
61    fn next_signal(&self) -> Signals {
62        match self.is_display_ownership_lost() {
63            true => *DISPLAY_OWNED,
64            false => *DISPLAY_UNOWNED,
65        }
66    }
67
68    /// Waits for the next signal change.
69    ///
70    /// If the display is owned, it will wait for display to become unowned.
71    /// If the display is unowned, it will wait for the display to become owned.
72    async fn wait_ownership_change<'a, T: AsHandleRef>(
73        &self,
74        event: &'a T,
75    ) -> Result<Signals, Status> {
76        OnSignals::new(event, self.next_signal()).await
77    }
78}
79
80/// A handler that turns the input pipeline off or on based on whether
81/// the Scenic owns the display.
82///
83/// This allows us to turn off keyboard processing when the user switches away
84/// from the product (e.g. terminal) into virtual console.
85///
86/// See the `README.md` file in this crate for details.
87///
88/// # Safety and Concurrency
89///
90/// This struct uses `RefCell` to manage internal state. While `DisplayOwnership`
91/// logic is split between multiple tasks (`handle_ownership_change` and
92/// `handle_unhandled_input_event`), safety is maintained because:
93/// 1. The pipeline runs on a single-threaded `LocalExecutor`.
94/// 2. Borrows of `RefCell`s (like `ownership` and `key_state`) are never held
95///    across `await` points.
96///
97/// If asynchronous calls are added to critical sections in the future,
98/// ensure that all borrows are dropped before the `await`.
99pub struct DisplayOwnership {
100    /// The current view of the display ownership.  It is mutated by the
101    /// display ownership task when appropriate signals arrive.
102    ownership: Rc<RefCell<Ownership>>,
103
104    /// The registry of currently pressed keys.
105    key_state: RefCell<KeyState>,
106
107    /// The source of ownership change events for the main loop.
108    display_ownership_change_receiver: RefCell<Option<UnboundedReceiver<Ownership>>>,
109
110    /// A background task that watches for display ownership changes.  We keep
111    /// it alive to ensure that it keeps running.
112    _display_ownership_task: Task<()>,
113
114    /// The metrics logger.
115    metrics_logger: metrics::MetricsLogger,
116
117    /// The inventory of this handler's Inspect status.
118    inspect_status: InputHandlerStatus,
119
120    /// The event processing loop will do an `unbounded_send(())` on this
121    /// channel once at the end of each loop pass, in test configurations only.
122    /// The test fixture uses this channel to execute test fixture in
123    /// lock-step with the event processing loop for test cases where the
124    /// precise event sequencing is relevant.
125    #[cfg(test)]
126    loop_done: RefCell<Option<UnboundedSender<()>>>,
127}
128
129impl DisplayOwnership {
130    /// Creates a new handler that watches `display_ownership_event` for events.
131    ///
132    /// The `display_ownership_event` is assumed to be an [Event] obtained from
133    /// `fuchsia.ui.composition.internal.DisplayOwnership/GetEvent`.  There
134    /// isn't really a way for this code to know here whether this is true or
135    /// not, so implementor beware.
136    pub fn new(
137        display_ownership_event: impl AsHandleRef + 'static,
138        input_handlers_node: &fuchsia_inspect::Node,
139        metrics_logger: metrics::MetricsLogger,
140    ) -> Rc<Self> {
141        DisplayOwnership::new_internal(
142            display_ownership_event,
143            None,
144            input_handlers_node,
145            metrics_logger,
146        )
147    }
148
149    #[cfg(test)]
150    pub fn new_for_test(
151        display_ownership_event: impl AsHandleRef + 'static,
152        loop_done: UnboundedSender<()>,
153        metrics_logger: metrics::MetricsLogger,
154    ) -> Rc<Self> {
155        let inspector = fuchsia_inspect::Inspector::default();
156        let fake_handlers_node = inspector.root().create_child("input_handlers_node");
157        DisplayOwnership::new_internal(
158            display_ownership_event,
159            Some(loop_done),
160            &fake_handlers_node,
161            metrics_logger,
162        )
163    }
164
165    fn new_internal(
166        display_ownership_event: impl AsHandleRef + 'static,
167        _loop_done: Option<UnboundedSender<()>>,
168        input_handlers_node: &fuchsia_inspect::Node,
169        metrics_logger: metrics::MetricsLogger,
170    ) -> Rc<Self> {
171        let initial_state = display_ownership_event
172            // scenic guarantees that ANY_DISPLAY_EVENT is asserted. If it is
173            // not, this will fail with a timeout error.
174            .as_handle_ref()
175            .wait_one(*ANY_DISPLAY_EVENT, MonotonicInstant::INFINITE_PAST)
176            .expect("unable to set the initial display state");
177        log::debug!("setting initial display ownership to: {:?}", &initial_state);
178        let initial_ownership: Ownership = initial_state.into();
179        let ownership = Rc::new(RefCell::new(initial_ownership.clone()));
180
181        let mut ownership_clone = initial_ownership;
182        let (ownership_sender, ownership_receiver) = mpsc::unbounded();
183        let display_ownership_task = Task::local(async move {
184            loop {
185                let signals = ownership_clone.wait_ownership_change(&display_ownership_event).await;
186                match signals {
187                    Err(e) => {
188                        log::warn!("could not read display state: {:?}", e);
189                        break;
190                    }
191                    Ok(signals) => {
192                        log::debug!("setting display ownership to: {:?}", &signals);
193                        ownership_sender.unbounded_send(signals.into()).unwrap();
194                        ownership_clone = signals.into();
195                    }
196                }
197            }
198            log::warn!(
199                "display loop exiting and will no longer monitor display changes - this is not expected"
200            );
201        });
202        log::info!("Display ownership handler installed");
203        let inspect_status = InputHandlerStatus::new(
204            input_handlers_node,
205            "display_ownership",
206            /* generates_events */ false,
207        );
208        Rc::new(Self {
209            ownership,
210            key_state: RefCell::new(KeyState::new()),
211            display_ownership_change_receiver: RefCell::new(Some(ownership_receiver)),
212            _display_ownership_task: display_ownership_task,
213            metrics_logger,
214            inspect_status,
215            #[cfg(test)]
216            loop_done: RefCell::new(_loop_done),
217        })
218    }
219
220    /// Returns true if the display is currently *not* owned by Scenic.
221    fn is_display_ownership_lost(&self) -> bool {
222        self.ownership.borrow().is_display_ownership_lost()
223    }
224
225    /// Watches for display ownership changes and sends cancel/sync events.
226    ///
227    /// NOTE: RefCell safety relies on the single-threaded nature of the executor.
228    /// No borrows of `ownership` or `key_state` must be held across the `await`
229    /// below to avoid panics if `handle_unhandled_input_event` runs while this
230    /// task is suspended.
231    pub async fn handle_ownership_change(
232        self: &Rc<Self>,
233        output: UnboundedSender<Vec<InputEvent>>,
234    ) -> Result<()> {
235        let mut ownership_source = self
236            .display_ownership_change_receiver
237            .borrow_mut()
238            .take()
239            .context("display_ownership_change_receiver already taken")?;
240        while let Some(new_ownership) = ownership_source.next().await {
241            let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
242            // When the ownership is modified, float a set of cancel or sync
243            // events to scoop up stale keyboard state, treating it the same
244            // as loss of focus.
245            let event_type = match is_display_ownership_lost {
246                true => KeyEventType::Cancel,
247                false => KeyEventType::Sync,
248            };
249            let keys = self.key_state.borrow().get_set();
250            let mut event_time = MonotonicInstant::get();
251            for key in keys.into_iter() {
252                let key_event = KeyboardEvent::new(key, event_type);
253                output
254                    .unbounded_send(vec![into_input_event(key_event, event_time)])
255                    .context("unable to send display updates")?;
256                event_time = event_time + MonotonicDuration::from_nanos(1);
257            }
258            *(self.ownership.borrow_mut()) = new_ownership;
259            #[cfg(test)]
260            {
261                if let Some(loop_done) = self.loop_done.borrow().as_ref() {
262                    loop_done.unbounded_send(()).unwrap();
263                }
264            }
265        }
266        Ok(())
267    }
268}
269
270impl Handler for DisplayOwnership {
271    fn set_handler_healthy(self: std::rc::Rc<Self>) {
272        self.inspect_status.health_node.borrow_mut().set_ok();
273    }
274
275    fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
276        self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
277    }
278
279    fn get_name(&self) -> &'static str {
280        "DisplayOwnership"
281    }
282
283    fn interest(&self) -> Vec<input_device::InputEventType> {
284        vec![input_device::InputEventType::Keyboard]
285    }
286}
287
288#[async_trait(?Send)]
289impl UnhandledInputHandler for DisplayOwnership {
290    async fn handle_unhandled_input_event(
291        self: Rc<Self>,
292        unhandled_input_event: UnhandledInputEvent,
293    ) -> Vec<input_device::InputEvent> {
294        fuchsia_trace::duration!("input", "display_ownership");
295        self.inspect_status.count_received_event(&unhandled_input_event.event_time);
296        match unhandled_input_event.device_event {
297            input_device::InputDeviceEvent::Keyboard(ref e) => {
298                self.key_state.borrow_mut().update(e.get_event_type(), e.get_key());
299            }
300            _ => {
301                self.metrics_logger.log_error(
302                    InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
303                    std::format!(
304                        "{} uninterested input event: {:?}",
305                        self.get_name(),
306                        unhandled_input_event.get_event_type()
307                    ),
308                );
309            }
310        }
311        let is_display_ownership_lost = self.is_display_ownership_lost();
312        if is_display_ownership_lost {
313            self.inspect_status.count_handled_event();
314        }
315
316        #[cfg(test)]
317        {
318            if let Some(loop_done) = self.loop_done.borrow().as_ref() {
319                loop_done.unbounded_send(()).unwrap();
320            }
321        }
322
323        vec![
324            input_device::InputEvent::from(unhandled_input_event)
325                .into_handled_if(is_display_ownership_lost),
326        ]
327    }
328}
329
330fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
331    input_device::InputDeviceDescriptor::Keyboard(
332        // Should descriptor be something sensible?
333        KeyboardDeviceDescriptor {
334            keys: vec![],
335            device_information: fidl_fuchsia_input_report::DeviceInformation {
336                vendor_id: Some(0),
337                product_id: Some(0),
338                version: Some(0),
339                polling_rate: Some(0),
340                ..Default::default()
341            },
342            device_id: 0,
343        },
344    )
345}
346
347fn into_input_event(
348    keyboard_event: KeyboardEvent,
349    event_time: MonotonicInstant,
350) -> input_device::InputEvent {
351    input_device::InputEvent {
352        device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
353        device_descriptor: empty_keyboard_device_descriptor(),
354        event_time,
355        handled: input_device::Handled::No,
356        trace_id: None,
357    }
358}
359
360#[cfg(test)]
361mod tests {
362    use super::*;
363    use crate::testing_utilities::{create_fake_input_event, create_input_event};
364    use fidl_fuchsia_input::Key;
365    use fuchsia_async as fasync;
366    use pretty_assertions::assert_eq;
367    use std::convert::TryFrom as _;
368    use zx::{EventPair, Peered};
369
370    // Manages losing and regaining display, since manual management is error-prone:
371    // if signal_peer does not change the signal state, the waiting process will block
372    // forever, which makes tests run longer than needed.
373    struct DisplayWrangler {
374        event: EventPair,
375        last: Signals,
376    }
377
378    impl DisplayWrangler {
379        fn new(event: EventPair) -> Self {
380            let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
381            // Signal needs to be initialized before the handlers attempts to read it.
382            // This is normally always the case in production.
383            // Else, the `new_for_test` below will panic with a TIMEOUT error.
384            instance.set_unowned();
385            instance
386        }
387
388        fn set_unowned(&mut self) {
389            assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
390            self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
391            self.last = *DISPLAY_UNOWNED;
392        }
393
394        fn set_owned(&mut self) {
395            assert!(self.last != *DISPLAY_OWNED, "display is already owned");
396            self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
397            self.last = *DISPLAY_OWNED;
398        }
399    }
400
401    #[fuchsia::test]
402    async fn display_ownership_change() {
403        // handler_event is the event that the unit under test will examine for
404        // display ownership changes.  test_event is used to set the appropriate
405        // signals.
406        let (test_event, handler_event) = EventPair::create();
407
408        // test_sender is used to pipe input events into the handler.
409        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
410
411        // test_receiver is used to pipe input events out of the handler.
412        let (handler_sender, test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
413
414        // The unit under test adds a () each time it completes one pass through
415        // its event loop.  Use to ensure synchronization.
416        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
417
418        // We use a wrapper to signal test_event correctly, since doing it wrong
419        // by hand causes tests to hang, which isn't the best dev experience.
420        let mut wrangler = DisplayWrangler::new(test_event);
421        let handler = DisplayOwnership::new_for_test(
422            handler_event,
423            loop_done_sender,
424            metrics::MetricsLogger::default(),
425        );
426
427        let handler_clone = handler.clone();
428        let handler_sender_clone = handler_sender.clone();
429        let _task = fasync::Task::local(async move {
430            handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
431        });
432
433        let handler_clone_2 = handler.clone();
434        let _input_task = fasync::Task::local(async move {
435            let mut receiver = handler_receiver;
436            while let Some(event) = receiver.next().await {
437                let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
438                let out_events =
439                    handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
440                handler_sender.unbounded_send(out_events).unwrap();
441            }
442        });
443
444        let fake_time = MonotonicInstant::from_nanos(42);
445
446        // Go two full circles of signaling.
447
448        // 1
449        wrangler.set_owned();
450        loop_done.next().await;
451        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
452        loop_done.next().await;
453
454        // 2
455        wrangler.set_unowned();
456        loop_done.next().await;
457        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
458        loop_done.next().await;
459
460        // 3
461        wrangler.set_owned();
462        loop_done.next().await;
463        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
464        loop_done.next().await;
465
466        // 4
467        wrangler.set_unowned();
468        loop_done.next().await;
469        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
470        loop_done.next().await;
471
472        let actual: Vec<InputEvent> = test_receiver
473            .take(4)
474            .flat_map(|events| futures::stream::iter(events))
475            .map(|e| e.into_with_event_time(fake_time))
476            .collect()
477            .await;
478
479        assert_eq!(
480            actual,
481            vec![
482                // Event received while we owned the display.
483                create_fake_input_event(fake_time),
484                // Event received when we lost the display.
485                create_fake_input_event(fake_time).into_handled(),
486                // Display ownership regained.
487                create_fake_input_event(fake_time),
488                // Display ownership lost.
489                create_fake_input_event(fake_time).into_handled(),
490            ]
491        );
492    }
493
494    fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
495        let fake_time = MonotonicInstant::from_nanos(42);
496        create_input_event(
497            KeyboardEvent::new(key, event_type),
498            &input_device::InputDeviceDescriptor::Fake,
499            fake_time,
500            input_device::Handled::No,
501        )
502    }
503
504    #[fuchsia::test]
505    async fn basic_key_state_handling() {
506        let (test_event, handler_event) = EventPair::create();
507        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
508        let (handler_sender, test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
509        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
510        let mut wrangler = DisplayWrangler::new(test_event);
511        let handler = DisplayOwnership::new_for_test(
512            handler_event,
513            loop_done_sender,
514            metrics::MetricsLogger::default(),
515        );
516
517        let handler_clone = handler.clone();
518        let handler_sender_clone = handler_sender.clone();
519        let _task = fasync::Task::local(async move {
520            handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
521        });
522
523        let handler_clone_2 = handler.clone();
524        let _input_task = fasync::Task::local(async move {
525            let mut receiver = handler_receiver;
526            while let Some(event) = receiver.next().await {
527                let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
528                let out_events =
529                    handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
530                handler_sender.unbounded_send(out_events).unwrap();
531            }
532        });
533
534        let fake_time = MonotonicInstant::from_nanos(42);
535
536        // Gain the display, and press a key.
537        wrangler.set_owned();
538        loop_done.next().await;
539        test_sender
540            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
541            .unwrap();
542        loop_done.next().await;
543
544        // Lose display.
545        wrangler.set_unowned();
546        loop_done.next().await;
547
548        // Regain display
549        wrangler.set_owned();
550        loop_done.next().await;
551
552        // Key event after regaining.
553        test_sender
554            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
555            .unwrap();
556        loop_done.next().await;
557
558        let actual: Vec<InputEvent> = test_receiver
559            .take(4)
560            .flat_map(|events| futures::stream::iter(events))
561            .map(|e| e.into_with_event_time(fake_time))
562            .collect()
563            .await;
564
565        assert_eq!(
566            actual,
567            vec![
568                new_keyboard_input_event(Key::A, KeyEventType::Pressed),
569                new_keyboard_input_event(Key::A, KeyEventType::Cancel)
570                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
571                new_keyboard_input_event(Key::A, KeyEventType::Sync)
572                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
573                new_keyboard_input_event(Key::A, KeyEventType::Released),
574            ]
575        );
576    }
577
578    #[fuchsia::test]
579    async fn more_key_state_handling() {
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::<Vec<InputEvent>>();
583        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
584        let mut wrangler = DisplayWrangler::new(test_event);
585        let handler = DisplayOwnership::new_for_test(
586            handler_event,
587            loop_done_sender,
588            metrics::MetricsLogger::default(),
589        );
590
591        let handler_clone = handler.clone();
592        let handler_sender_clone = handler_sender.clone();
593        let _task = fasync::Task::local(async move {
594            handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
595        });
596
597        let handler_clone_2 = handler.clone();
598        let _input_task = fasync::Task::local(async move {
599            let mut receiver = handler_receiver;
600            while let Some(event) = receiver.next().await {
601                let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
602                let out_events =
603                    handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
604                handler_sender.unbounded_send(out_events).unwrap();
605            }
606        });
607
608        let fake_time = MonotonicInstant::from_nanos(42);
609
610        wrangler.set_owned();
611        loop_done.next().await;
612        test_sender
613            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
614            .unwrap();
615        loop_done.next().await;
616        test_sender
617            .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
618            .unwrap();
619        loop_done.next().await;
620
621        // Lose display, release a key, press a key.
622        wrangler.set_unowned();
623        loop_done.next().await;
624        test_sender
625            .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
626            .unwrap();
627        loop_done.next().await;
628        test_sender
629            .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
630            .unwrap();
631        loop_done.next().await;
632
633        // Regain display
634        wrangler.set_owned();
635        loop_done.next().await;
636
637        // Key event after regaining.
638        test_sender
639            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
640            .unwrap();
641        loop_done.next().await;
642        test_sender
643            .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
644            .unwrap();
645        loop_done.next().await;
646
647        let actual: Vec<InputEvent> = test_receiver
648            .take(10) // 2 pressed, 2 cancelled, 1 released (handled), 1 pressed (handled), 2 synced, 2 released
649            .flat_map(|events| futures::stream::iter(events))
650            .map(|e| e.into_with_event_time(fake_time))
651            .collect()
652            .await;
653
654        assert_eq!(
655            actual,
656            vec![
657                new_keyboard_input_event(Key::A, KeyEventType::Pressed),
658                new_keyboard_input_event(Key::B, KeyEventType::Pressed),
659                new_keyboard_input_event(Key::A, KeyEventType::Cancel)
660                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
661                new_keyboard_input_event(Key::B, KeyEventType::Cancel)
662                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
663                new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
664                new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
665                // The CANCEL and SYNC events are emitted in the sort ordering of the
666                // `Key` enum values. Perhaps they should be emitted instead in the order
667                // they have been received for SYNC, and in reverse order for CANCEL.
668                new_keyboard_input_event(Key::A, KeyEventType::Sync)
669                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
670                new_keyboard_input_event(Key::C, KeyEventType::Sync)
671                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
672                new_keyboard_input_event(Key::A, KeyEventType::Released),
673                new_keyboard_input_event(Key::C, KeyEventType::Released),
674            ]
675        );
676    }
677
678    #[fuchsia::test]
679    async fn display_ownership_initialized_with_inspect_node() {
680        let (test_event, handler_event) = EventPair::create();
681        let (loop_done_sender, _) = mpsc::unbounded::<()>();
682        let inspector = fuchsia_inspect::Inspector::default();
683        let fake_handlers_node = inspector.root().create_child("input_handlers_node");
684        // Signal needs to be initialized first so DisplayOwnership::new doesn't panic with a TIMEOUT error
685        let _ = DisplayWrangler::new(test_event);
686        let _handler = DisplayOwnership::new_internal(
687            handler_event,
688            Some(loop_done_sender),
689            &fake_handlers_node,
690            metrics::MetricsLogger::default(),
691        );
692        diagnostics_assertions::assert_data_tree!(inspector, root: {
693            input_handlers_node: {
694                display_ownership: {
695                    events_received_count: 0u64,
696                    events_handled_count: 0u64,
697                    last_received_timestamp_ns: 0u64,
698                    "fuchsia.inspect.Health": {
699                        status: "STARTING_UP",
700                        // Timestamp value is unpredictable and not relevant in this context,
701                        // so we only assert that the property is present.
702                        start_timestamp_nanos: diagnostics_assertions::AnyProperty
703                    },
704                }
705            }
706        });
707    }
708
709    #[fuchsia::test]
710    async fn display_ownership_inspect_counts_events() {
711        let (test_event, handler_event) = EventPair::create();
712        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
713        let (handler_sender, _test_receiver) = mpsc::unbounded::<Vec<InputEvent>>();
714        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
715        let mut wrangler = DisplayWrangler::new(test_event);
716        let inspector = fuchsia_inspect::Inspector::default();
717        let fake_handlers_node = inspector.root().create_child("input_handlers_node");
718        let handler = DisplayOwnership::new_internal(
719            handler_event,
720            Some(loop_done_sender),
721            &fake_handlers_node,
722            metrics::MetricsLogger::default(),
723        );
724        let handler_clone = handler.clone();
725        let handler_sender_clone = handler_sender.clone();
726        let _task = fasync::Task::local(async move {
727            handler_clone.handle_ownership_change(handler_sender_clone).await.unwrap();
728        });
729
730        let handler_clone_2 = handler.clone();
731        let _input_task = fasync::Task::local(async move {
732            let mut receiver = handler_receiver;
733            while let Some(event) = receiver.next().await {
734                let unhandled_event = UnhandledInputEvent::try_from(event).unwrap();
735                let out_events =
736                    handler_clone_2.clone().handle_unhandled_input_event(unhandled_event).await;
737                handler_sender.unbounded_send(out_events).unwrap();
738            }
739        });
740
741        // Gain the display, and press a key.
742        wrangler.set_owned();
743        loop_done.next().await;
744        test_sender
745            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
746            .unwrap();
747        loop_done.next().await;
748
749        // Lose display
750        // Input event is marked `Handled` if received after display ownership is lost
751        wrangler.set_unowned();
752        loop_done.next().await;
753        test_sender
754            .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
755            .unwrap();
756        loop_done.next().await;
757
758        // Regain display
759        wrangler.set_owned();
760        loop_done.next().await;
761
762        // Key event after regaining.
763        test_sender
764            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
765            .unwrap();
766        loop_done.next().await;
767
768        diagnostics_assertions::assert_data_tree!(inspector, root: {
769            input_handlers_node: {
770                display_ownership: {
771                    events_received_count: 3u64,
772                    events_handled_count: 1u64,
773                    last_received_timestamp_ns: 42u64,
774                    "fuchsia.inspect.Health": {
775                        status: "STARTING_UP",
776                        // Timestamp value is unpredictable and not relevant in this context,
777                        // so we only assert that the property is present.
778                        start_timestamp_nanos: diagnostics_assertions::AnyProperty
779                    },
780                }
781            }
782        });
783    }
784}