// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(fxbug.dev/89234): Check what happens with the modifier keys - we should perhaps maintain
// them.

//! Implements hardware key autorepeat.
//!
//! The [Autorepeater] is a bit of an exception among the stages of the input pipeline.  This
//! handler does not implement [input_pipeline::InputHandler], as it requires a different approach
//! to event processing.
//!
//! Specifically, it requires the ability to interleave the events it generates into the
//! flow of "regular" events through the input pipeline.  While the [input_pipeline::InputHandler]
//! trait could in principle be modified to admit this sort of approach to event processing, in
//! practice the [Autorepeater] is for now the only stage that requires this approach, so it is
//! not cost effective to retrofit all other handlers just for the sake of this one.  We may
//! revisit this decision if we grow more stages that need autorepeat.

use crate::input_device::{self, Handled, InputDeviceDescriptor, InputDeviceEvent, InputEvent};
use crate::keyboard_binding::KeyboardEvent;
use anyhow::{anyhow, Context, Result};
use fidl_fuchsia_settings as fsettings;
use fidl_fuchsia_ui_input3::{KeyEventType, KeyMeaning};
use fuchsia_async::{Task, Time, Timer};
use fuchsia_syslog::{fx_log_debug, fx_log_err, fx_log_info, fx_log_warn};
use fuchsia_zircon as zx;
use fuchsia_zircon::Duration;
use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
use futures::StreamExt;
use std::cell::RefCell;
use std::convert::TryInto;
use std::rc::Rc;

/// Typed autorepeat settings.  Use [Default::default()] and the `into_with_*`
/// to create a new instance.
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Settings {
    // The time delay before autorepeat kicks in.
    delay: Duration,
    // The average period between two successive autorepeats.  A reciprocal of
    // the autorepeat rate.
    period: Duration,
}

impl Default for Settings {
    fn default() -> Self {
        Settings { delay: Duration::from_millis(250), period: Duration::from_millis(50) }
    }
}

impl From<fsettings::Autorepeat> for Settings {
    /// Conversion, since [fsettings::Autorepeat] has untyped delay and period.
    fn from(s: fsettings::Autorepeat) -> Self {
        Self { delay: Duration::from_nanos(s.delay), period: Duration::from_nanos(s.period) }
    }
}

impl Settings {
    /// Modifies the delay.
    pub fn into_with_delay(self, delay: Duration) -> Self {
        Self { delay, ..self }
    }

    /// Modifies the period.
    pub fn into_with_period(self, period: Duration) -> Self {
        Self { period, ..self }
    }
}

// Whether the key is repeatable.
enum Repeatability {
    // The key may autorepeat.
    Yes,
    // The key may not autorepeat.
    No,
}

// Determines whether the given key meaning corresponds to a key that should be repeated.
//
// Roughly, the criterion is: if the key may contribute to text editing, it should be repeatable.
// The decisions taken below are a bit pragmatic, since our specification in the FIDL API is not
// exactly clear on when a key is repeatable.  Instead our rules are implicit in the way the key
// meaning is defined.
//
// To wit, nonzero code points are printable and therefore may repeat.
// NonPrintableKey are, paradoxically, repeatable, since the current examples of keys that are
// nonprintable are empirically repeatable.  Keys that are not repeatable have a zero as the
// codepoint - this is not an API requirement, but stems from the way we currently use it, so we
// may as well make it official.  The decisions may become obsolete as KeyMeaning evolves.
//
// TODO(fxbug.dev/89736): Sort out whether Left, Right, Up, Down etc should be nonprintable keys
// or keys with codepoint zero.
fn repeatability(key_meaning: Option<KeyMeaning>) -> Repeatability {
    match key_meaning {
        Some(KeyMeaning::Codepoint(0)) => Repeatability::No, // e.g. Shift
        Some(KeyMeaning::Codepoint(_)) => Repeatability::Yes, // A code point.
        // This will need to be extended when more nonprintable keys are introduced.
        Some(KeyMeaning::NonPrintableKey(_)) => Repeatability::Yes, // Tab, Enter, Backspace...
        None => Repeatability::Yes, // Printable with US QWERTY keymap.
    }
}

// An events multiplexer.
#[derive(Debug, Clone)]
enum AnyEvent {
    // A keyboard input event.
    Keyboard(KeyboardEvent, InputDeviceDescriptor, zx::Time, Handled),
    // An input event other than keyboard.
    NonKeyboard(InputEvent),
    // A timer event.
    Timeout,
}

impl TryInto<InputEvent> for AnyEvent {
    type Error = anyhow::Error;

    fn try_into(self) -> Result<InputEvent> {
        match self {
            AnyEvent::NonKeyboard(ev) => Ok(ev),
            AnyEvent::Keyboard(ev, device_descriptor, event_time, handled) => Ok(InputEvent {
                device_event: InputDeviceEvent::Keyboard(ev.clone().into_with_folded_event()),
                device_descriptor: device_descriptor.clone(),
                event_time,
                handled,
                trace_id: None,
            }),
            _ => Err(anyhow!("not an InputEvent: {:?}", &self)),
        }
    }
}

// The state of the autorepeat generator.
#[derive(Debug, Clone)]
enum State {
    /// Autorepeat is not active.
    Dormant,
    /// Autorepeat is armed, we are waiting for a timer event to expire, and when
    /// it does, we generate a repeat event.
    Armed {
        // The keyboard event that caused the state to become Armed.
        armed_event: KeyboardEvent,
        // The descriptor is used to reconstruct an InputEvent when needed.
        armed_descriptor: InputDeviceDescriptor,
        // The autorepeat timer is used in the various stages of autorepeat
        // waits.
        // Not used directly, but rather kept because of its side effect.
        _delay_timer: Rc<Task<()>>,
    },
}

impl Default for State {
    fn default() -> Self {
        State::Dormant
    }
}

// Logs an `event` before sending to `sink` for debugging.
fn unbounded_send_logged<T>(sink: &UnboundedSender<T>, event: T) -> Result<()>
where
    for<'a> &'a T: std::fmt::Debug,
    T: 'static + Sync + Send,
{
    fx_log_debug!("unbounded_send_logged: {:?}", &event);
    sink.unbounded_send(event)?;
    Ok(())
}

/// Creates a new autorepeat timer task.
///
/// The task will wait for the amount of time given in `delay`, and then send
/// a [AnyEvent::Timeout] to `sink`; unless it is canceled.
fn new_autorepeat_timer(sink: UnboundedSender<AnyEvent>, delay: Duration) -> Rc<Task<()>> {
    let task = Task::local(async move {
        Timer::new(Time::after(delay)).await;
        fx_log_debug!("autorepeat timeout");
        unbounded_send_logged(&sink, AnyEvent::Timeout)
            .unwrap_or_else(|e| fx_log_err!("could not fire autorepeat timer: {:?}", e));
    });
    Rc::new(task)
}

/// Maintains the internal autorepeat state.
///
/// The autorepeat tracks key presses and generates autorepeat key events for
/// the keys that are eligible for autorepeat.
pub struct Autorepeater {
    // Internal events are multiplexed into this sender.  We may make multiple
    // clones to serialize async events.
    event_sink: UnboundedSender<AnyEvent>,

    // This end is consumed to get the multiplexed ordered events.
    event_source: RefCell<UnboundedReceiver<AnyEvent>>,

    // The current autorepeat state.
    state: RefCell<State>,

    // The autorepeat settings.
    settings: Settings,

    // The task that feeds input events into the processing loop.
    _event_feeder: Task<()>,
}

impl Autorepeater {
    /// Creates a new [Autorepeater].  The `source` is a receiver end through which
    /// the input pipeline events are sent.  You must submit [Autorepeater::run]
    /// to an executor to start the event processing.
    pub fn new(source: UnboundedReceiver<InputEvent>) -> Rc<Self> {
        Self::new_with_settings(source, Default::default())
    }

    fn new_with_settings(
        mut source: UnboundedReceiver<InputEvent>,
        settings: Settings,
    ) -> Rc<Self> {
        let (event_sink, event_source) = mpsc::unbounded();

        // We need a task to feed input events into the channel read by `run()`.
        // The task will run until there is at least one sender. When there
        // are no more senders, `source.next().await` will return None, and
        // this task will exit.  The task will close the `event_sink` to
        // signal to the other end that it will send no more events, which can
        // be used for orderly shutdown.
        let event_feeder = {
            let event_sink = event_sink.clone();
            Task::local(async move {
                while let Some(event) = source.next().await {
                    match event {
                        InputEvent {
                            device_event: InputDeviceEvent::Keyboard(k),
                            device_descriptor,
                            event_time,
                            handled,
                            trace_id: _,
                        } if handled == Handled::No => unbounded_send_logged(
                            &event_sink,
                            AnyEvent::Keyboard(k, device_descriptor, event_time, handled),
                        )
                        .context("while forwarding a keyboard event"),
                        InputEvent {
                            device_event: _,
                            device_descriptor: _,
                            event_time: _,
                            handled: _,
                            trace_id: _,
                        } => unbounded_send_logged(&event_sink, AnyEvent::NonKeyboard(event))
                            .context("while forwarding a non-keyboard event"),
                    }
                    .unwrap_or_else(|e| fx_log_err!("could not run autorepeat: {:?}", e));
                }
                event_sink.close_channel();
            })
        };

        Rc::new(Autorepeater {
            event_sink,
            event_source: RefCell::new(event_source),
            state: RefCell::new(Default::default()),
            settings,
            _event_feeder: event_feeder,
        })
    }

    /// Run this function in an executor to start processing events. The
    /// transformed event stream is available in `output`.
    pub async fn run(self: &Rc<Self>, output: UnboundedSender<InputEvent>) -> Result<()> {
        fx_log_info!("key autorepeater installed");
        let src = &mut *(self.event_source.borrow_mut());
        while let Some(event) = src.next().await {
            match event {
                // Anything not a keyboard or any handled event gets forwarded as is.
                AnyEvent::NonKeyboard(input_event) => unbounded_send_logged(&output, input_event)?,
                AnyEvent::Keyboard(_, _, _, _) | AnyEvent::Timeout => {
                    self.process_event(event, &output).await?
                }
            }
        }
        // If we got to here, that means `src` was closed.
        // Ensure that the channel closure is propagated correctly.
        output.close_channel();

        // In production we never expect `src` to close as the autorepeater
        // should be operating continuously, so if we're here and we're in prod
        // this is unexpected. That is why we return an error.
        //
        // But, in tests it is acceptable to ignore this error and let the
        // function return.  An orderly shutdown will result.
        Err(anyhow!("recv loop is never supposed to terminate"))
    }

    // Replace the autorepeater state with a new one.
    fn set_state(self: &Rc<Self>, state: State) {
        fx_log_debug!("set state: {:?}", &state);
        self.state.replace(state);
    }

    // Get a copy of the current autorepeater state.
    fn get_state(self: &Rc<Self>) -> State {
        self.state.borrow().clone()
    }

    // Process a single `event`.  Any forwarded or generated events are emitted
    // into `output.
    async fn process_event(
        self: &Rc<Self>,
        event: AnyEvent,
        output: &UnboundedSender<InputEvent>,
    ) -> Result<()> {
        let old_state = self.get_state();
        fx_log_debug!("process_event: current state: {:?}", &old_state);
        fx_log_debug!("process_event: inbound event: {:?}", &event);
        match (old_state, event.clone()) {
            // This is the initial state.  We wait for a key event with a printable
            // character, since those are autorepeatable.
            (State::Dormant, AnyEvent::Keyboard(ev, descriptor, ..)) => {
                match (ev.get_event_type_folded(), repeatability(ev.get_key_meaning())) {
                    // Only a printable key is a candidate for repeating.
                    // We start a delay timer and go to waiting.
                    (KeyEventType::Pressed, Repeatability::Yes) => {
                        let _delay_timer =
                            new_autorepeat_timer(self.event_sink.clone(), self.settings.delay);
                        self.set_state(State::Armed {
                            armed_event: ev,
                            armed_descriptor: descriptor,
                            _delay_timer,
                        });
                    }

                    // Any other key type or key event does not get repeated.
                    (_, _) => {}
                }
                unbounded_send_logged(&output, event.try_into()?)?;
            }

            // A timeout comes while we are in dormant state.  We expect
            // no timeouts in this state. Perhaps this is a timer task
            // that fired after it was canceled?  In any case, do not act on it,
            // but issue a warning.
            (State::Dormant, AnyEvent::Timeout) => {
                // This is unexpected, but not fatal.  If you see this in the
                // logs, we probably need to revisit the fuchsia_async::Task
                // semantics.
                fx_log_warn!("spurious timeout in the autorepeater");
            }

            // A keyboard event comes in while autorepeat is armed.
            //
            // If the keyboard event comes in about the same key that was armed, we
            // restart the repeat timer, to ensure repeated keypresses on the
            // same key don't generate even more repetitions.
            //
            // If the keyboard event is about a different repeatable key, we
            // restart the autorepeat timer with the new key.  This means that
            // an autorepeated sequence 'aaaaaabbbbbb' will pause for an
            // additional repeat delay between the last 'a' and the first 'b'
            // in the sequence.
            //
            // In all cases, pass the event onwards.  No events are dropped
            // from the event stream.
            (State::Armed { armed_event, .. }, AnyEvent::Keyboard(ev, descriptor, ..)) => {
                let ev = ev.clone();
                match (ev.get_event_type_folded(), repeatability(ev.get_key_meaning())) {
                    (KeyEventType::Pressed, Repeatability::Yes) => {
                        let _delay_timer =
                            new_autorepeat_timer(self.event_sink.clone(), self.settings.delay);
                        self.set_state(State::Armed {
                            armed_event: ev,
                            armed_descriptor: descriptor,
                            _delay_timer,
                        });
                    }

                    (KeyEventType::Released, Repeatability::Yes) => {
                        // If the armed key was released, stop autorepeat.
                        // If the release was for another key, remain in the
                        // armed state.
                        if KeyboardEvent::same_key(&armed_event, &ev) {
                            self.set_state(State::Dormant);
                        }
                    }

                    // Any other event causes nothing special to happen.
                    _ => {}
                }
                unbounded_send_logged(&output, event.try_into()?)?;
            }

            // The timeout triggered while we are armed.  This is an autorepeat!
            (State::Armed { armed_event, armed_descriptor, .. }, AnyEvent::Timeout) => {
                let _delay_timer =
                    new_autorepeat_timer(self.event_sink.clone(), self.settings.period);
                let new_event = armed_event
                    .clone()
                    .into_with_repeat_sequence(armed_event.get_repeat_sequence() + 1);
                let new_event_time = input_device::event_time_or_now(None);

                self.set_state(State::Armed {
                    armed_event: new_event.clone(),
                    armed_descriptor: armed_descriptor.clone(),
                    _delay_timer,
                });
                // Generate a new autorepeat event and ship it out.
                let autorepeat_event =
                    AnyEvent::Keyboard(new_event, armed_descriptor, new_event_time, Handled::No);
                unbounded_send_logged(&output, autorepeat_event.try_into()?)?;
            }

            // Forward all other events unmodified.
            (_, AnyEvent::NonKeyboard(event)) => {
                unbounded_send_logged(&output, event)?;
            }
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::testing_utilities;
    use fidl_fuchsia_input::Key;
    use fuchsia_async::TestExecutor;
    use fuchsia_zircon as zx;
    use futures::Future;
    use pin_utils::pin_mut;
    use pretty_assertions::assert_eq;
    use std::task::Poll;

    // Default autorepeat settings used for test.  If these settings are changed,
    // any tests may fail, since the tests are tuned to the precise timing that
    // is set here.
    fn default_settings() -> Settings {
        Settings { delay: Duration::from_millis(500), period: Duration::from_seconds(1) }
    }

    // Creates a new keyboard event for testing.
    fn new_event(
        key: Key,
        event_type: KeyEventType,
        key_meaning: Option<KeyMeaning>,
        repeat_sequence: u32,
    ) -> InputEvent {
        testing_utilities::create_keyboard_event_with_key_meaning_and_repeat_sequence(
            key,
            event_type,
            /*modifiers=*/ None,
            /*event_time*/ zx::Time::ZERO,
            &InputDeviceDescriptor::Fake,
            /*keymap=*/ None,
            key_meaning,
            repeat_sequence,
        )
    }

    fn new_handled_event(
        key: Key,
        event_type: KeyEventType,
        key_meaning: Option<KeyMeaning>,
        repeat_sequence: u32,
    ) -> InputEvent {
        let event = new_event(key, event_type, key_meaning, repeat_sequence);
        // Somewhat surprisingly, this works.
        InputEvent { handled: Handled::Yes, ..event }
    }

    // A shorthand for blocking the specified number of milliseconds, asynchronously.
    async fn wait_for_millis(millis: i64) {
        wait_for_duration(zx::Duration::from_millis(millis)).await;
    }

    async fn wait_for_duration(duration: Duration) {
        fuchsia_async::Timer::new(Time::after(duration)).await;
    }

    // Strip event time for these events, for comparison.  The event times are
    // unpredictable since they are read off of the real time monotonic clock,
    // and will be different in every run.
    fn remove_event_time(events: Vec<InputEvent>) -> Vec<InputEvent> {
        events
            .into_iter()
            .map(
                |InputEvent {
                     device_event,
                     device_descriptor,
                     event_time: _,
                     handled,
                     trace_id: _,
                 }| {
                    InputEvent {
                        device_event,
                        device_descriptor,
                        event_time: zx::Time::ZERO,
                        handled,
                        trace_id: None,
                    }
                },
            )
            .collect()
    }

    // Wait for this long (in fake time) before asserting events to ensure
    // that all events have been drained and all timers have fired.
    const SLACK_DURATION: Duration = zx::Duration::from_millis(5000);

    // Checks whether the events read from `output` match supplied `expected` events.
    async fn assert_events(output: UnboundedReceiver<InputEvent>, expected: Vec<InputEvent>) {
        // Spends a little while longer in the processing loop to ensure that all events have been
        // drained before we take the events out.  The wait is in fake time, so it does not
        // introduce nondeterminism into the tests.
        wait_for_duration(SLACK_DURATION).await;
        assert_eq!(
            remove_event_time(output.take(expected.len()).collect::<Vec<InputEvent>>().await),
            expected
        );
    }

    // Run the future `main_fut` in fake time.  The fake time is being advanced
    // in relatively small increments until a specified `total_duration` has
    // elapsed.
    //
    // This complication is needed to ensure that any expired
    // timers are awoken in the correct sequence because the test executor does
    // not automatically wake the timers. For the fake time execution to
    // be comparable to a real time execution, we need each timer to have the
    // chance of waking up, so that we can properly process the consequences
    // of that timer firing.
    //
    // We require that `main_fut` has completed at `total_duration`, and panic
    // if it has not.  This ensures that we never block forever in fake time.
    //
    // This method could possibly be implemented in [TestExecutor] for those
    // test executor users who do not care to wake the timers in any special
    // way.
    fn run_in_fake_time<F>(executor: &mut TestExecutor, main_fut: &mut F, total_duration: Duration)
    where
        F: Future<Output = ()> + Unpin,
    {
        const INCREMENT: Duration = zx::Duration::from_millis(13);
        // Run the loop for a bit longer than the fake time needed to pump all
        // the events, to allow the event queue to drain.
        let total_duration = total_duration + SLACK_DURATION;
        let mut current = zx::Duration::from_millis(0);
        let mut poll_status = Poll::Pending;

        // We run until either the future completes or the timeout is reached,
        // whichever comes first.
        // Running the future after it returns Poll::Ready is not allowed, so
        // we must exit the loop then.
        while current < total_duration && poll_status == Poll::Pending {
            executor.set_fake_time(Time::after(INCREMENT));
            executor.wake_expired_timers();
            poll_status = executor.run_until_stalled(main_fut);
            current = current + INCREMENT;
        }
        assert_eq!(
            poll_status,
            Poll::Ready(()),
            "the main future did not complete, perhaps increase total_duration?"
        );
    }

    // A general note for all the tests here.
    //
    // The autorepeat generator is tightly coupled with the real time clock. Such
    // a system would be hard to test robustly if we relied on the passage of
    // real time, since we can not do precise pauses, and are sensitive to
    // the scheduling delays in the emulators that run the tests.
    //
    // Instead, we use an executor with fake time: we have to advance the fake
    // time manually, and poke the executor such that we eventually run through
    // the predictable sequence of scheduled asynchronous events.
    //
    // The first few tests in this suite will have extra comments that explain
    // the general testing techniques.  Repeated uses of the same techniques
    // will not be specially pointed out in the later tests.

    // This test pushes a regular key press and release through the autorepeat
    // handler. It is used more to explain how the event processing works, than
    // it is exercising a specific feature of the autorepeat handler.
    #[test]
    fn basic_press_and_release_only() {
        // TestExecutor puts itself as the thread local executor. Any local
        // task spawned from here on will run on the test executor in fake time,
        // and will need `run_with_fake_time` to drive it to completion.
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        // `input` is where the test fixture will inject the fake input events.
        // `receiver` is where the autorepeater will read these events from.
        let (input, receiver) = mpsc::unbounded();

        // The autorepeat handler takes a receiver end of one channel to get
        // the input from, and the send end of another channel to place the
        // output into. Since we must formally start the handling process in
        // an async task, the API requires you to call `run` to
        // start the process and supply the sender side of the output.
        //
        // This API ensures that the handler is fully configured when started,
        // all the while leaving the user with an option of when and how exactly
        // to start the handler, including not immediately upon creation.
        let handler = Autorepeater::new_with_settings(receiver, default_settings());

        // `sender` is where the autorepeat handler will send processed input
        // events into.  `output` is where we will read the results of the
        // autorepeater's work.
        let (sender, output) = mpsc::unbounded();

        // It is up to the caller to decide where to spawn the handler task.
        let handler_task = Task::local(async move { handler.run(sender).await });

        // `main_fut` is the task that exercises the handler.
        let main_fut = async move {
            // Inject a keyboard event into the autorepeater.
            //
            // The mpsc channel of which 'input' is the receiver will be closed when all consumers
            // go out of scope.
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            // This will wait in fake time.  The tests are not actually delayed because of this
            // call.
            wait_for_millis(1).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            // Assertions are also here in the async domain since reading from
            // output must be asynchronous.
            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };

        // Drive both the test fixture task and the handler task in parallel,
        // and both in fake time.  `run_in_fake_time` advances the fake time from
        // zero in increments of about 10ms until all futures complete.
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    #[test]
    fn basic_sync_and_cancel_only() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();
        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Sync,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();
            wait_for_millis(1).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Cancel,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();
            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    // Ensures that we forward but not act on handled events.
    #[test]
    fn handled_events_are_forwarded() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();
        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_handled_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_handled_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_handled_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_handled_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };

        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    // In this test, we wait with a pressed key for long enough that the default
    // settings should trigger the autorepeat.
    #[test]
    fn autorepeat_simple() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            // The total fake time during which the autorepeat key was actuated
            // was 2 seconds.  By default the delay to first autorepeat is 500ms,
            // then 1000ms for each additional autorepeat. This means we should
            // see three `Pressed` events: one at the outset, a second one after
            // 500ms, and a third one after 1500ms.
            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        2,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    // This test is the same as above, but we hold the autorepeat for a little
    // while longer and check that the autorepeat event stream has grown
    // accordingly.
    #[test]
    fn autorepeat_simple_longer() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(3000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        2,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        3,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    // In this test, keys A and B compete for autorepeat:
    //
    //     @0ms ->|<- 1.6s ->|<- 2s ->|<- 1s ->|
    // A """""""""\___________________/"""""""""""""
    //            :          :                 :
    // B """"""""""""""""""""\_________________/""""
    #[test]
    fn autorepeat_takeover() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(1600).await;

            input
                .unbounded_send(new_event(
                    Key::B,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('b' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(1000).await;

            input
                .unbounded_send(new_event(
                    Key::B,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('b' as u32)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        2,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        0,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        1,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        2,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        3,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    // In this test, keys A and B compete for autorepeat:
    //
    //     @0ms ->|<- 2s ->|<- 2s ->|<- 2s ->|
    // A """""""""\__________________________/""""
    //            :        :        :        :
    // B """"""""""""""""""\________/"""""""""""""
    #[test]
    fn autorepeat_takeover_and_back() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::B,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('b' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::B,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('b' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('a' as u32)),
                    0,
                ))
                .unwrap();

            // Try to elicit autorepeat.  There won't be any.
            wait_for_millis(2000).await;

            assert_events(
                output,
                vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        2,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        0,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        1,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        2,
                    ),
                    new_event(
                        Key::B,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('b' as u32)),
                        0,
                    ),
                    // No autorepeat after B is released.
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('a' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    #[test]
    fn no_autorepeat_for_left_shift() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Pressed,
                    // Keys that do not contribute to text editing have code
                    // point set to zero. We use this as a discriminator for
                    // which keys may or may not repeat.
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            wait_for_millis(5000).await;

            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    //       @0ms ->|<- 2s ->|<- 2s ->|<- 2s ->|
    // A         """"""""""""\________/"""""""""""""
    // LeftShift """\__________________________/""""
    #[test]
    fn shift_a_encapsulated() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('A' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('A' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        2,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        0,
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = Task::local(async move {
            let _r = futures::join!(handler_task, main_fut);
        });
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }

    //       @0ms ->|<- 2s ->|<- 2s ->|<- 2s ->|
    // A         """"""""""""\_________________/""
    // LeftShift """\_________________/"""""""""""
    #[test]
    fn shift_a_interleaved() {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();

        let (input, receiver) = mpsc::unbounded();
        let handler = Autorepeater::new_with_settings(receiver, default_settings());
        let (sender, output) = mpsc::unbounded();
        let handler_task = Task::local(async move { handler.run(sender).await });

        let main_fut = async move {
            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Pressed,
                    Some(KeyMeaning::Codepoint('A' as u32)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::LeftShift,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint(0)),
                    0,
                ))
                .unwrap();

            wait_for_millis(2000).await;

            input
                .unbounded_send(new_event(
                    Key::A,
                    KeyEventType::Released,
                    Some(KeyMeaning::Codepoint('A' as u32)),
                    0,
                ))
                .unwrap();

            assert_events(
                output,
                vec![
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        0,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        1,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        2,
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(0)),
                        0,
                    ),
                    // This will continue autorepeating capital A, but we'd need
                    // to autorepeat 'a'.  May need to reapply the keymap at
                    // this point, but this may require redoing the keymap stage.
                    // Alternative - stop autorepeat, would be easier.
                    // The current behavior may be enough, however.
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        3,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        4,
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                        0,
                    ),
                ],
            )
            .await;
        };
        let joined_fut = async move {
            let _r = futures::join!(main_fut, handler_task);
        };
        pin_mut!(joined_fut);
        run_in_fake_time(&mut executor, &mut joined_fut, zx::Duration::from_seconds(10));
    }
}
