Skip to main content

input_synthesis/modern_backend/
input_device.rs

1// Copyright 2020 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
5#![warn(missing_docs)]
6
7use crate::modern_backend::input_reports_reader::InputReportsReaderV2;
8use crate::synthesizer;
9use crate::usages::hid_usage_to_input3_key;
10use anyhow::{Context as _, Error, format_err};
11use async_trait::async_trait;
12use fidl::Error as FidlError;
13use fidl::endpoints::ServerEnd;
14use fidl_fuchsia_input::Key;
15use fidl_fuchsia_input_report::{
16    ConsumerControlButton, ConsumerControlInputReport, ContactInputReport, DeviceDescriptor,
17    FeatureReport, InputDeviceRequest, InputDeviceRequestStream, InputReport,
18    InputReportsReaderV2Marker, KeyboardInputReport, MouseInputReport, TOUCH_MAX_CONTACTS,
19    TouchInputReport,
20};
21use fidl_fuchsia_ui_input::{KeyboardReport, Touch};
22use fuchsia_async as fasync;
23use futures::{StreamExt, TryFutureExt, future, pin_mut};
24use std::convert::TryFrom as _;
25
26/// Implements the `synthesizer::InputDevice` trait, and the server side of the
27/// `fuchsia.input.report.InputDevice` FIDL protocol. Used by
28/// `modern_backend::InputDeviceRegistry`.
29///
30/// # Notes
31/// * Some of the methods of `fuchsia.input.report.InputDevice` are not relevant to
32///   input injection, so this implemnentation does not support them:
33///   * `SendOutputReport` provides a way to change keyboard LED state.
34///   If these FIDL methods are invoked, `InputDevice::flush()` will resolve to Err.
35/// * This implementation does not support multiple calls to `GetInputReportsReaderV2`,
36///   since:
37///   * The ideal semantics for multiple calls are not obvious, and
38///   * Each `InputDevice` has a single FIDL client (an input pipeline implementation),
39///     and the current input pipeline implementation is happy to use a single
40///     `InputReportsReaderV2` for the lifetime of the `InputDevice`.
41pub(super) struct InputDevice {
42    /// FIFO queue of reports to be consumed by calls to
43    /// `fuchsia.input.report.InputReportsReader.ReadInputReports()`.
44    /// Populated by calls to `synthesizer::InputDevice` trait methods.
45    report_sender: futures::channel::mpsc::UnboundedSender<InputReport>,
46
47    // `Task` to keep serving the `fuchsia.input.report.InputDevice` protocol.
48    input_device_task: fasync::Task<Result<(), Error>>,
49}
50
51impl std::convert::From<synthesizer::MediaButton> for ConsumerControlButton {
52    fn from(synthesizer_button: synthesizer::MediaButton) -> Self {
53        match synthesizer_button {
54            synthesizer::MediaButton::VolumeUp => Self::VolumeUp,
55            synthesizer::MediaButton::VolumeDown => Self::VolumeDown,
56            synthesizer::MediaButton::MicMute => Self::MicMute,
57            synthesizer::MediaButton::FactoryReset => Self::FactoryReset,
58            synthesizer::MediaButton::Pause => Self::Pause,
59            synthesizer::MediaButton::CameraDisable => Self::CameraDisable,
60        }
61    }
62}
63
64#[async_trait(?Send)]
65impl synthesizer::InputDevice for self::InputDevice {
66    fn media_buttons(
67        &mut self,
68        pressed_buttons: Vec<synthesizer::MediaButton>,
69        time: u64,
70    ) -> Result<(), Error> {
71        self.report_sender
72            .unbounded_send(InputReport {
73                event_time: Some(i64::try_from(time).context("converting time to i64")?),
74                consumer_control: Some(ConsumerControlInputReport {
75                    pressed_buttons: Some(pressed_buttons.into_iter().map(Into::into).collect()),
76                    ..Default::default()
77                }),
78                ..Default::default()
79            })
80            .context("sending media button InputReport")
81    }
82
83    // TODO(https://fxbug.dev/42142533): remove dependency on HID usage codes.
84    fn key_press(&mut self, report: KeyboardReport, time: u64) -> Result<(), Error> {
85        self.key_press_internal(report, time, Self::convert_keyboard_report_to_keys)
86    }
87
88    fn key_press_raw(&mut self, report: KeyboardReport, time: u64) -> Result<(), Error> {
89        self.key_press_internal(report, time, Self::convert_keyboard_report_to_keys_no_transform)
90    }
91
92    // TODO(https://fxbug.dev/42142533): remove reference to HID usage codes.
93    fn key_press_usage(&mut self, usage: Option<u32>, time: u64) -> Result<(), Error> {
94        self.key_press(KeyboardReport { pressed_keys: usage.into_iter().collect() }, time)
95    }
96
97    fn tap(&mut self, pos: Option<(u32, u32)>, time: u64) -> Result<(), Error> {
98        let fingers = pos.and_then(|(x, y)| {
99            Some(vec![Touch { finger_id: 1, x: x as i32, y: y as i32, width: 0, height: 0 }])
100        });
101        self.multi_finger_tap(fingers, time)
102    }
103
104    fn multi_finger_tap(&mut self, fingers: Option<Vec<Touch>>, time: u64) -> Result<(), Error> {
105        let num_fingers = match &fingers {
106            Some(fingers_vec) => fingers_vec.len(),
107            None => 0,
108        };
109        if num_fingers > usize::try_from(TOUCH_MAX_CONTACTS).context("usize is at least 32 bits")? {
110            return Err(format_err!(
111                "Got {} fingers, but max is {}",
112                num_fingers,
113                TOUCH_MAX_CONTACTS
114            ));
115        }
116        self.multi_finger_tap_internal(
117            TouchInputReport {
118                contacts: Some(fingers.map_or_else(Vec::new, |fingers_vec| {
119                    fingers_vec
120                        .into_iter()
121                        .map(|finger| ContactInputReport {
122                            contact_id: Some(finger.finger_id),
123                            position_x: Some(i64::from(finger.x)),
124                            position_y: Some(i64::from(finger.y)),
125                            contact_width: Some(i64::from(finger.width)),
126                            contact_height: Some(i64::from(finger.height)),
127                            ..Default::default()
128                        })
129                        .collect()
130                })),
131                pressed_buttons: Some(vec![]),
132                ..Default::default()
133            },
134            time,
135        )
136    }
137
138    fn mouse(&mut self, report: MouseInputReport, time: u64) -> Result<(), Error> {
139        self.report_sender
140            .unbounded_send(InputReport {
141                event_time: Some(i64::try_from(time).context("converting time to i64")?),
142                mouse: Some(report),
143                ..Default::default()
144            })
145            .context("error sending mouse InputReport")
146    }
147
148    async fn flush(self: Box<Self>) -> Result<(), Error> {
149        let Self { input_device_task, report_sender } = *self;
150        std::mem::drop(report_sender); // Drop `report_sender` to close channel.
151        input_device_task.await
152    }
153}
154
155impl InputDevice {
156    /// Creates a new `InputDevice` that will create a task to:
157    /// a) process requests from `request_stream`, and
158    /// b) respond to `GetDescriptor` calls with the descriptor generated by `descriptor_generator()`
159    pub(super) fn new(
160        request_stream: InputDeviceRequestStream,
161        descriptor: DeviceDescriptor,
162    ) -> Self {
163        let (report_sender, report_receiver) = futures::channel::mpsc::unbounded::<InputReport>();
164
165        // Create a `Task` to keep serving the `fuchsia.input.report.InputDevice` protocol.
166        let input_device_task =
167            fasync::Task::local(Self::serve_reports(request_stream, descriptor, report_receiver));
168
169        Self { report_sender, input_device_task }
170    }
171
172    /// Returns a `Future` which resolves when all `InputReport`s for this device
173    /// have been sent to a `fuchsia.input.report.InputReportsReaderV2` client, or when
174    /// an error occurs.
175    ///
176    /// # Resolves to
177    /// * `Ok(())` if all reports were written successfully
178    /// * `Err` otherwise. For example:
179    ///   * The `fuchsia.input.report.InputDevice` client sent an invalid request.
180    ///   * A FIDL error occurred while trying to read a FIDL request.
181    ///   * A FIDL error occurred while trying to write a FIDL response.
182    ///
183    /// # Corner cases
184    /// Resolves to `Err` if the `fuchsia.input.report.InputDevice` client did not call
185    /// `GetInputReportsReaderV2()`, even if no `InputReport`s were queued.
186    ///
187    /// # Note
188    /// When the `Future` resolves, `InputReports` may still be sitting unread in the
189    /// channel to the `fuchsia.input.report.InputReportsReaderV2` client. (The client will
190    /// typically be an input pipeline implementation.)
191    async fn serve_reports(
192        request_stream: InputDeviceRequestStream,
193        descriptor: DeviceDescriptor,
194        report_receiver: futures::channel::mpsc::UnboundedReceiver<InputReport>,
195    ) -> Result<(), Error> {
196        // Process `fuchsia.input.report.InputDevice` requests, waiting for the `InputDevice`
197        // client to provide a `ServerEnd<InputReportsReaderV2Marker>` by calling `GetInputReportsReaderV2()`.
198        let mut input_reports_reader_server_end_stream = request_stream
199            .filter_map(|r| future::ready(Self::handle_device_request(r, &descriptor)));
200        let input_reports_reader_fut = {
201            let (reader_server_end, max_unacknowledged_reports) =
202                input_reports_reader_server_end_stream
203                    .next()
204                    .await
205                    .ok_or_else(|| {
206                        format_err!("stream ended without a call to GetInputReportsReaderV2")
207                    })?
208                    .context("handling InputDeviceRequest")?;
209            InputReportsReaderV2 {
210                request_stream: reader_server_end.into_stream(),
211                report_receiver,
212                max_unacknowledged_reports,
213            }
214            .into_future()
215        };
216        pin_mut!(input_reports_reader_fut);
217
218        // Create a `Future` to keep serving the `fuchsia.input.report.InputDevice` protocol.
219        // This time, receiving a `ServerEnd<InputReportsReaderV2Marker>` will be an `Err`.
220        let input_device_server_fut = async {
221            match input_reports_reader_server_end_stream.next().await {
222                Some(Ok(_server_end)) => {
223                    // There are no obvious "best" semantics for how to handle multiple
224                    // `GetInputReportsReaderV2` calls, and there is no current need to
225                    // do so. Instead of taking a guess at what the client might want
226                    // in such a case, just return `Err`.
227                    Err(format_err!(
228                        "InputDevice does not support multiple GetInputReportsReaderV2 calls"
229                    ))
230                }
231                Some(Err(e)) => Err(e.context("handling InputDeviceRequest")),
232                None => Ok(()),
233            }
234        };
235        pin_mut!(input_device_server_fut);
236
237        // Now, process both `fuchsia.input.report.InputDevice` requests, and
238        // `fuchsia.input.report.InputReportsReaderV2` requests. And keep processing
239        // `InputReportsReaderV2` requests even if the `InputDevice` connection
240        // is severed.
241        future::select(
242            input_device_server_fut.and_then(|_: ()| future::pending()),
243            input_reports_reader_fut,
244        )
245        .await
246        .factor_first()
247        .0
248    }
249
250    /// Converts a [KeyboardReport] into a sequence of key presses, using the supplied
251    /// key-to-HID usage transformation function.
252    fn key_press_internal(
253        &mut self,
254        report: KeyboardReport,
255        time: u64,
256        transform: fn(r: &KeyboardReport) -> Result<Vec<Key>, Error>,
257    ) -> Result<(), Error> {
258        self.report_sender
259            .unbounded_send(InputReport {
260                event_time: Some(i64::try_from(time).context("converting time to i64")?),
261                keyboard: Some(KeyboardInputReport {
262                    pressed_keys3: Some(transform(&report)?),
263                    ..Default::default()
264                }),
265                ..Default::default()
266            })
267            .context("sending key press InputReport")
268    }
269
270    fn multi_finger_tap_internal(
271        &mut self,
272        touch: TouchInputReport,
273        time: u64,
274    ) -> Result<(), Error> {
275        self.report_sender
276            .unbounded_send(InputReport {
277                event_time: Some(i64::try_from(time).context("converting time to i64")?),
278                touch: Some(touch),
279                ..Default::default()
280            })
281            .context("sending touch InputReport")
282    }
283
284    /// Processes a single request from an `InputDeviceRequestStream`
285    ///
286    /// # Returns
287    /// * Some(Ok((ServerEnd<InputReportsReaderV2Marker>, u16))) if the request yielded an `InputReportsReaderV2`.
288    /// * Some(Err) if the request yielded an `Error`
289    /// * None if the request was fully processed by `handle_device_request()`
290    fn handle_device_request(
291        request: Result<InputDeviceRequest, FidlError>,
292        descriptor: &DeviceDescriptor,
293    ) -> Option<Result<(ServerEnd<InputReportsReaderV2Marker>, u16), Error>> {
294        match request {
295            Ok(InputDeviceRequest::GetInputReportsReaderV2 {
296                reader: reader_server_end,
297                max_unacknowledged_reports_limit,
298                responder,
299            }) => {
300                let max_unacknowledged_reports = max_unacknowledged_reports_limit.max(1);
301                if let Err(e) = responder.send(max_unacknowledged_reports) {
302                    return Some(Err(
303                        anyhow::Error::from(e).context("sending GetInputReportsReaderV2 response")
304                    ));
305                }
306                Some(Ok((reader_server_end, max_unacknowledged_reports)))
307            }
308            Ok(InputDeviceRequest::GetDescriptor { responder }) => {
309                match responder.send(&descriptor) {
310                    Ok(()) => None,
311                    Err(e) => {
312                        Some(Err(anyhow::Error::from(e).context("sending GetDescriptor response")))
313                    }
314                }
315            }
316            Ok(InputDeviceRequest::GetFeatureReport { responder }) => {
317                match responder.send(Ok(&FeatureReport::default())) {
318                    Ok(()) => None,
319                    Err(e) => Some(Err(
320                        anyhow::Error::from(e).context("sending GetFeatureReport response")
321                    )),
322                }
323            }
324            Err(e) => {
325                // Fail fast.
326                //
327                // Panic here, since we don't have a good way to report an error from a
328                // background task.  InputDevice::flush() exists, but this is unlikely
329                // to be called in tests, and it may get called way too late, after
330                // an error in this background task already caused some other error.
331                panic!("InputDevice got an error while reading request: {:?}", e);
332            }
333            _ => {
334                // See the previous branch.
335                panic!(
336                    "InputDevice::handle_device_request does not support this request: {:?}",
337                    request
338                );
339            }
340        }
341    }
342
343    fn convert_keyboard_report_to_keys(report: &KeyboardReport) -> Result<Vec<Key>, Error> {
344        report
345            .pressed_keys
346            .iter()
347            .map(|&usage| {
348                hid_usage_to_input3_key(usage as u16)
349                    .ok_or_else(|| format_err!("no Key for usage {:?}", usage))
350            })
351            .collect()
352    }
353
354    /// Same as convert_keyboard_report_to_keys, but no additional calls to HID usage mapping.
355    ///
356    /// The keyboard report in `convert_keyboard_report_to_keys` assumes USB HID usage page 7.
357    /// This set of keys is narrower than what Fuchsia supports so that function needs to map
358    /// back into Fuchsia USB HID encoding (see [fidl_fuchsia_input::Key]).
359    ///
360    /// This function, in turn, uses the full range of [fidl_fuchsia_input::Key], so does not
361    /// need this conversion.
362    fn convert_keyboard_report_to_keys_no_transform(
363        report: &KeyboardReport,
364    ) -> Result<Vec<Key>, Error> {
365        report
366            .pressed_keys
367            .iter()
368            .map(|&usage| {
369                Key::from_primitive(usage)
370                    .ok_or_else(|| anyhow::anyhow!("could not convert to input::Key: {}", usage))
371            })
372            .collect()
373    }
374}
375
376#[cfg(test)]
377mod tests {
378    use super::synthesizer::InputDevice as _;
379    use super::*;
380    use fidl::endpoints;
381    use fidl_fuchsia_input_report::{
382        DeviceDescriptor, InputDeviceMarker, KeyboardDescriptor, KeyboardInputDescriptor,
383    };
384    use fuchsia_async as fasync;
385
386    const DEFAULT_REPORT_TIMESTAMP: u64 = 0;
387
388    mod responds_to_get_feature_report_request {
389        use super::*;
390
391        #[fasync::run_until_stalled(test)]
392        async fn single_request_before_call_to_get_feature_report() -> Result<(), Error> {
393            let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
394            let input_device_server_fut =
395                Box::new(InputDevice::new(request_stream, DeviceDescriptor::default())).flush();
396            let get_feature_report_fut = proxy.get_feature_report();
397            std::mem::drop(proxy); // Drop `proxy` to terminate `request_stream`.
398
399            let (_, get_feature_report_result) =
400                future::join(input_device_server_fut, get_feature_report_fut).await;
401            assert_eq!(
402                get_feature_report_result.context("fidl error")?,
403                Ok(FeatureReport::default())
404            );
405            Ok(())
406        }
407    }
408
409    mod responds_to_get_descriptor_request {
410        use super::utils::{make_input_device_proxy_and_struct, make_keyboard_descriptor};
411        use super::*;
412        use assert_matches::assert_matches;
413        use futures::task::Poll;
414
415        #[fasync::run_until_stalled(test)]
416        async fn single_request_before_call_to_get_input_reports_reader() -> Result<(), Error> {
417            let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
418            let input_device_server_fut =
419                Box::new(InputDevice::new(request_stream, make_keyboard_descriptor(vec![Key::A])))
420                    .flush();
421            let get_descriptor_fut = proxy.get_descriptor();
422            std::mem::drop(proxy); // Drop `proxy` to terminate `request_stream`.
423
424            let (_, get_descriptor_result) =
425                future::join(input_device_server_fut, get_descriptor_fut).await;
426            assert_eq!(
427                get_descriptor_result.context("fidl error")?,
428                make_keyboard_descriptor(vec![Key::A])
429            );
430            Ok(())
431        }
432
433        #[test]
434        fn multiple_requests_before_call_to_get_input_reports_reader() -> Result<(), Error> {
435            let mut executor = fasync::TestExecutor::new();
436            let (proxy, request_stream) = endpoints::create_proxy_and_stream::<InputDeviceMarker>();
437            let mut input_device_server_fut =
438                Box::new(InputDevice::new(request_stream, make_keyboard_descriptor(vec![Key::A])))
439                    .flush();
440
441            let mut get_descriptor_fut = proxy.get_descriptor();
442            assert_matches!(
443                executor.run_until_stalled(&mut input_device_server_fut),
444                Poll::Pending
445            );
446            std::mem::drop(executor.run_until_stalled(&mut get_descriptor_fut));
447
448            let mut get_descriptor_fut = proxy.get_descriptor();
449            let _ = executor.run_until_stalled(&mut input_device_server_fut);
450            assert_matches!(
451                executor.run_until_stalled(&mut get_descriptor_fut),
452                Poll::Ready(Ok(_))
453            );
454
455            Ok(())
456        }
457
458        #[test]
459        fn after_call_to_get_input_reports_reader_with_report_pending() -> Result<(), Error> {
460            let mut executor = fasync::TestExecutor::new();
461            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
462            for _ in 0..2 {
463                input_device
464                    .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
465                    .context("internal error queuing input event")?;
466            }
467
468            let input_device_server_fut = input_device.flush();
469            pin_mut!(input_device_server_fut);
470
471            let (_input_reports_reader_proxy, input_reports_reader_server_end) =
472                endpoints::create_proxy::<InputReportsReaderV2Marker>();
473
474            const MAX_UNACKNOWLEDGED_REPORTS_LIMIT: u16 = 1;
475            let _ = input_device_proxy.get_input_reports_reader_v2(
476                input_reports_reader_server_end,
477                MAX_UNACKNOWLEDGED_REPORTS_LIMIT,
478            );
479            assert_matches!(
480                executor.run_until_stalled(&mut input_device_server_fut),
481                Poll::Pending
482            );
483
484            let mut get_descriptor_fut = input_device_proxy.get_descriptor();
485            assert_matches!(
486                executor.run_until_stalled(&mut input_device_server_fut),
487                Poll::Pending
488            );
489            assert_matches!(executor.run_until_stalled(&mut get_descriptor_fut), Poll::Ready(_));
490            Ok(())
491        }
492    }
493
494    mod report_contents {
495        use super::utils::{get_input_reports, make_input_device_proxy_and_struct};
496        use super::*;
497        use crate::usages::Usages;
498        use assert_matches::assert_matches;
499        use std::convert::TryInto as _;
500
501        #[fasync::run_until_stalled(test)]
502        async fn media_buttons_generates_empty_consumer_controls_input_report() -> Result<(), Error>
503        {
504            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
505            input_device.media_buttons(vec![], DEFAULT_REPORT_TIMESTAMP)?;
506
507            let input_reports = get_input_reports(input_device, input_device_proxy).await;
508            assert_eq!(
509                input_reports.as_slice(),
510                [InputReport {
511                    event_time: Some(
512                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
513                    ),
514                    consumer_control: Some(ConsumerControlInputReport {
515                        pressed_buttons: Some(vec![]),
516                        ..Default::default()
517                    }),
518                    ..Default::default()
519                }]
520            );
521            Ok(())
522        }
523
524        #[fasync::run_until_stalled(test)]
525        async fn media_buttons_generates_full_consumer_controls_input_report() -> Result<(), Error>
526        {
527            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
528            input_device.media_buttons(
529                vec![
530                    synthesizer::MediaButton::VolumeUp,
531                    synthesizer::MediaButton::VolumeDown,
532                    synthesizer::MediaButton::MicMute,
533                    synthesizer::MediaButton::FactoryReset,
534                    synthesizer::MediaButton::Pause,
535                    synthesizer::MediaButton::CameraDisable,
536                ],
537                DEFAULT_REPORT_TIMESTAMP,
538            )?;
539
540            let input_reports = get_input_reports(input_device, input_device_proxy).await;
541            assert_eq!(
542                input_reports.as_slice(),
543                [InputReport {
544                    event_time: Some(
545                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
546                    ),
547                    consumer_control: Some(ConsumerControlInputReport {
548                        pressed_buttons: Some(vec![
549                            ConsumerControlButton::VolumeUp,
550                            ConsumerControlButton::VolumeDown,
551                            ConsumerControlButton::MicMute,
552                            ConsumerControlButton::FactoryReset,
553                            ConsumerControlButton::Pause,
554                            ConsumerControlButton::CameraDisable,
555                        ]),
556                        ..Default::default()
557                    }),
558                    ..Default::default()
559                }]
560            );
561            Ok(())
562        }
563
564        #[fasync::run_until_stalled(test)]
565        async fn media_buttons_generates_partial_consumer_controls_input_report()
566        -> Result<(), Error> {
567            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
568            input_device.media_buttons(
569                vec![
570                    synthesizer::MediaButton::VolumeUp,
571                    synthesizer::MediaButton::MicMute,
572                    synthesizer::MediaButton::Pause,
573                ],
574                DEFAULT_REPORT_TIMESTAMP,
575            )?;
576
577            let input_reports = get_input_reports(input_device, input_device_proxy).await;
578            assert_eq!(
579                input_reports.as_slice(),
580                [InputReport {
581                    event_time: Some(
582                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
583                    ),
584                    consumer_control: Some(ConsumerControlInputReport {
585                        pressed_buttons: Some(vec![
586                            ConsumerControlButton::VolumeUp,
587                            ConsumerControlButton::MicMute,
588                            ConsumerControlButton::Pause,
589                        ]),
590                        ..Default::default()
591                    }),
592                    ..Default::default()
593                }]
594            );
595            Ok(())
596        }
597
598        #[fasync::run_until_stalled(test)]
599        async fn key_press_generates_expected_keyboard_input_report() -> Result<(), Error> {
600            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
601            input_device.key_press(
602                KeyboardReport {
603                    pressed_keys: vec![Usages::HidUsageKeyA as u32, Usages::HidUsageKeyB as u32],
604                },
605                DEFAULT_REPORT_TIMESTAMP,
606            )?;
607
608            let input_reports = get_input_reports(input_device, input_device_proxy).await;
609            assert_eq!(
610                input_reports.as_slice(),
611                [InputReport {
612                    event_time: Some(
613                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
614                    ),
615                    keyboard: Some(KeyboardInputReport {
616                        pressed_keys3: Some(vec![Key::A, Key::B]),
617                        ..Default::default()
618                    }),
619                    ..Default::default()
620                }]
621            );
622            Ok(())
623        }
624
625        #[fasync::run_until_stalled(test)]
626        async fn key_press_usage_generates_expected_keyboard_input_report_for_some()
627        -> Result<(), Error> {
628            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
629            input_device
630                .key_press_usage(Some(Usages::HidUsageKeyA as u32), DEFAULT_REPORT_TIMESTAMP)?;
631
632            let input_reports = get_input_reports(input_device, input_device_proxy).await;
633            assert_eq!(
634                input_reports.as_slice(),
635                [InputReport {
636                    event_time: Some(
637                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
638                    ),
639                    keyboard: Some(KeyboardInputReport {
640                        pressed_keys3: Some(vec![Key::A]),
641                        ..Default::default()
642                    }),
643                    ..Default::default()
644                }]
645            );
646            Ok(())
647        }
648
649        #[fasync::run_until_stalled(test)]
650        async fn key_press_usage_generates_expected_keyboard_input_report_for_none()
651        -> Result<(), Error> {
652            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
653            input_device.key_press_usage(None, DEFAULT_REPORT_TIMESTAMP)?;
654
655            let input_reports = get_input_reports(input_device, input_device_proxy).await;
656            assert_eq!(
657                input_reports.as_slice(),
658                [InputReport {
659                    event_time: Some(
660                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
661                    ),
662                    keyboard: Some(KeyboardInputReport {
663                        pressed_keys3: Some(vec![]),
664                        ..Default::default()
665                    }),
666                    ..Default::default()
667                }]
668            );
669            Ok(())
670        }
671
672        #[fasync::run_until_stalled(test)]
673        async fn key_press_returns_error_if_usage_cannot_be_mapped_to_key() {
674            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
675            assert_matches!(
676                input_device.key_press(
677                    KeyboardReport { pressed_keys: vec![0xffff_ffff] },
678                    DEFAULT_REPORT_TIMESTAMP
679                ),
680                Err(_)
681            );
682        }
683
684        #[fasync::run_until_stalled(test)]
685        async fn key_press_usage_returns_error_if_usage_cannot_be_mapped_to_key() {
686            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
687            assert_matches!(
688                input_device.key_press_usage(Some(0xffff_ffff), DEFAULT_REPORT_TIMESTAMP),
689                Err(_)
690            );
691        }
692
693        #[fasync::run_until_stalled(test)]
694        async fn key_events_generates_expected_keyboard_response() -> Result<(), Error> {
695            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
696            input_device.key_press_raw(
697                KeyboardReport {
698                    pressed_keys: vec![Key::A.into_primitive(), Key::B.into_primitive()],
699                },
700                DEFAULT_REPORT_TIMESTAMP,
701            )?;
702
703            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
704            assert_eq!(
705                input_reports.as_slice(),
706                [InputReport {
707                    event_time: Some(
708                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
709                    ),
710                    keyboard: Some(KeyboardInputReport {
711                        pressed_keys3: Some(vec![Key::A, Key::B]),
712                        ..Default::default()
713                    }),
714                    ..Default::default()
715                }]
716            );
717            Ok(())
718        }
719
720        #[fasync::run_until_stalled(test)]
721        async fn tap_generates_expected_report_for_some() -> Result<(), Error> {
722            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
723            input_device.tap(Some((10, 20)), DEFAULT_REPORT_TIMESTAMP)?;
724
725            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
726            assert_eq!(
727                input_reports.as_slice(),
728                [InputReport {
729                    event_time: Some(
730                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
731                    ),
732                    touch: Some(TouchInputReport {
733                        contacts: Some(vec![ContactInputReport {
734                            contact_id: Some(1),
735                            position_x: Some(10),
736                            position_y: Some(20),
737                            pressure: None,
738                            contact_width: Some(0),
739                            contact_height: Some(0),
740                            ..Default::default()
741                        }]),
742                        pressed_buttons: Some(vec![]),
743                        ..Default::default()
744                    }),
745                    ..Default::default()
746                }]
747            );
748            Ok(())
749        }
750
751        #[fasync::run_until_stalled(test)]
752        async fn tap_generates_expected_report_for_none() -> Result<(), Error> {
753            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
754            input_device.tap(None, DEFAULT_REPORT_TIMESTAMP)?;
755
756            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
757            assert_eq!(
758                input_reports.as_slice(),
759                [InputReport {
760                    event_time: Some(
761                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
762                    ),
763                    touch: Some(TouchInputReport {
764                        contacts: Some(vec![]),
765                        pressed_buttons: Some(vec![]),
766                        ..Default::default()
767                    }),
768                    ..Default::default()
769                }]
770            );
771            Ok(())
772        }
773
774        #[fasync::run_until_stalled(test)]
775        async fn multi_finger_tap_generates_report_for_single_finger() -> Result<(), Error> {
776            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
777            input_device.multi_finger_tap(
778                Some(vec![Touch { finger_id: 5, x: 10, y: 20, width: 100, height: 200 }]),
779                DEFAULT_REPORT_TIMESTAMP,
780            )?;
781
782            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
783            assert_eq!(
784                input_reports.as_slice(),
785                [InputReport {
786                    event_time: Some(
787                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
788                    ),
789                    touch: Some(TouchInputReport {
790                        contacts: Some(vec![ContactInputReport {
791                            contact_id: Some(5),
792                            position_x: Some(10),
793                            position_y: Some(20),
794                            pressure: None,
795                            contact_width: Some(100),
796                            contact_height: Some(200),
797                            ..Default::default()
798                        }]),
799                        pressed_buttons: Some(vec![]),
800                        ..Default::default()
801                    }),
802                    ..Default::default()
803                }]
804            );
805            Ok(())
806        }
807
808        #[fasync::run_until_stalled(test)]
809        async fn multi_finger_tap_generates_expected_report_for_two_fingers() -> Result<(), Error> {
810            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
811            input_device.multi_finger_tap(
812                Some(vec![
813                    Touch { finger_id: 5, x: 10, y: 20, width: 100, height: 200 },
814                    Touch { finger_id: 0, x: 30, y: 40, width: 300, height: 400 },
815                ]),
816                DEFAULT_REPORT_TIMESTAMP,
817            )?;
818
819            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
820            assert_eq!(
821                input_reports.as_slice(),
822                [InputReport {
823                    event_time: Some(
824                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
825                    ),
826                    touch: Some(TouchInputReport {
827                        contacts: Some(vec![
828                            ContactInputReport {
829                                contact_id: Some(5),
830                                position_x: Some(10),
831                                position_y: Some(20),
832                                pressure: None,
833                                contact_width: Some(100),
834                                contact_height: Some(200),
835                                ..Default::default()
836                            },
837                            ContactInputReport {
838                                contact_id: Some(0),
839                                position_x: Some(30),
840                                position_y: Some(40),
841                                pressure: None,
842                                contact_width: Some(300),
843                                contact_height: Some(400),
844                                ..Default::default()
845                            }
846                        ]),
847                        pressed_buttons: Some(vec![]),
848                        ..Default::default()
849                    }),
850                    ..Default::default()
851                }]
852            );
853            Ok(())
854        }
855
856        #[fasync::run_until_stalled(test)]
857        async fn multi_finger_tap_generates_expected_report_for_zero_fingers() -> Result<(), Error>
858        {
859            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
860            input_device.multi_finger_tap(Some(vec![]), DEFAULT_REPORT_TIMESTAMP)?;
861
862            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
863            assert_eq!(
864                input_reports.as_slice(),
865                [InputReport {
866                    event_time: Some(
867                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
868                    ),
869                    touch: Some(TouchInputReport {
870                        contacts: Some(vec![]),
871                        pressed_buttons: Some(vec![]),
872                        ..Default::default()
873                    }),
874                    ..Default::default()
875                }]
876            );
877            Ok(())
878        }
879
880        #[fasync::run_until_stalled(test)]
881        async fn multi_finger_tap_generates_expected_report_for_none() -> Result<(), Error> {
882            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
883            input_device.multi_finger_tap(None, DEFAULT_REPORT_TIMESTAMP)?;
884
885            let input_reports = get_input_reports(input_device, _input_device_proxy).await;
886            assert_eq!(
887                input_reports.as_slice(),
888                [InputReport {
889                    event_time: Some(
890                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
891                    ),
892                    touch: Some(TouchInputReport {
893                        contacts: Some(vec![]),
894                        pressed_buttons: Some(vec![]),
895                        ..Default::default()
896                    }),
897                    ..Default::default()
898                }]
899            );
900            Ok(())
901        }
902
903        #[fasync::run_until_stalled(test)]
904        async fn multi_finger_tap_returns_error_when_num_fingers_is_to_large() {
905            let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
906            assert_matches!(
907                input_device.multi_finger_tap(
908                    Some(
909                        (0..=TOUCH_MAX_CONTACTS)
910                            .map(|i| Touch {
911                                finger_id: i,
912                                x: i as i32,
913                                y: i as i32,
914                                width: i,
915                                height: i
916                            })
917                            .collect(),
918                    ),
919                    DEFAULT_REPORT_TIMESTAMP,
920                ),
921                Err(_)
922            );
923        }
924
925        #[fasync::run_until_stalled(test)]
926        async fn mouse_generates_empty_mouse_input_report() -> Result<(), Error> {
927            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
928            input_device.mouse(MouseInputReport::default(), DEFAULT_REPORT_TIMESTAMP)?;
929
930            let input_reports = get_input_reports(input_device, input_device_proxy).await;
931            assert_eq!(
932                input_reports.as_slice(),
933                [InputReport {
934                    event_time: Some(
935                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
936                    ),
937                    mouse: Some(MouseInputReport::default()),
938                    ..Default::default()
939                }]
940            );
941            Ok(())
942        }
943
944        #[fasync::run_until_stalled(test)]
945        async fn mouse_generates_full_mouse_input_report() -> Result<(), Error> {
946            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
947            input_device.mouse(
948                MouseInputReport {
949                    movement_x: Some(10),
950                    movement_y: Some(15),
951                    pressed_buttons: Some(vec![1, 2, 3]),
952                    scroll_v: Some(1),
953                    scroll_h: Some(-1),
954                    ..Default::default()
955                },
956                DEFAULT_REPORT_TIMESTAMP,
957            )?;
958
959            let input_reports = get_input_reports(input_device, input_device_proxy).await;
960            assert_eq!(
961                input_reports.as_slice(),
962                [InputReport {
963                    event_time: Some(
964                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
965                    ),
966                    mouse: Some(MouseInputReport {
967                        movement_x: Some(10),
968                        movement_y: Some(15),
969                        pressed_buttons: Some(vec![1, 2, 3]),
970                        scroll_v: Some(1),
971                        scroll_h: Some(-1),
972                        ..Default::default()
973                    }),
974                    ..Default::default()
975                }]
976            );
977            Ok(())
978        }
979
980        #[fasync::run_until_stalled(test)]
981        async fn mouse_generates_partial_mouse_input_report() -> Result<(), Error> {
982            let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
983            input_device.mouse(
984                MouseInputReport {
985                    movement_x: Some(10),
986                    movement_y: Some(15),
987                    pressed_buttons: Some(vec![]),
988                    ..Default::default()
989                },
990                DEFAULT_REPORT_TIMESTAMP,
991            )?;
992
993            let input_reports = get_input_reports(input_device, input_device_proxy).await;
994            assert_eq!(
995                input_reports.as_slice(),
996                [InputReport {
997                    event_time: Some(
998                        DEFAULT_REPORT_TIMESTAMP.try_into().expect("converting to i64")
999                    ),
1000                    mouse: Some(MouseInputReport {
1001                        movement_x: Some(10),
1002                        movement_y: Some(15),
1003                        pressed_buttons: Some(vec![]),
1004                        ..Default::default()
1005                    }),
1006                    ..Default::default()
1007                }]
1008            );
1009            Ok(())
1010        }
1011    }
1012
1013    mod future_resolution {
1014        use super::utils::{make_input_device_proxy_and_struct, make_input_reports_reader_proxy};
1015        use super::*;
1016        use futures::task::Poll;
1017
1018        mod yields_ok_after_all_reports_are_sent_to_input_reports_reader {
1019            use super::*;
1020            use assert_matches::assert_matches;
1021
1022            #[test]
1023            fn if_device_request_channel_was_closed() {
1024                let mut executor = fasync::TestExecutor::new();
1025                let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1026                let _input_reports_reader_proxy =
1027                    make_input_reports_reader_proxy(&input_device_proxy);
1028                input_device
1029                    .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1030                    .expect("queuing input report");
1031
1032                let mut input_device_fut = input_device.flush();
1033                std::mem::drop(input_device_proxy); // Close device request channel.
1034                assert_matches!(
1035                    executor.run_until_stalled(&mut input_device_fut),
1036                    Poll::Ready(Ok(()))
1037                );
1038            }
1039
1040            #[test]
1041            fn even_if_device_request_channel_is_open() {
1042                let mut executor = fasync::TestExecutor::new();
1043                let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1044                let _input_reports_reader_proxy =
1045                    make_input_reports_reader_proxy(&input_device_proxy);
1046                input_device
1047                    .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1048                    .expect("queuing input report");
1049
1050                let mut input_device_fut = input_device.flush();
1051                assert_matches!(
1052                    executor.run_until_stalled(&mut input_device_fut),
1053                    Poll::Ready(Ok(()))
1054                );
1055            }
1056
1057            #[test]
1058            fn even_if_reports_was_empty_and_device_request_channel_is_open() {
1059                let mut executor = fasync::TestExecutor::new();
1060                let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1061                let _input_reports_reader_proxy =
1062                    make_input_reports_reader_proxy(&input_device_proxy);
1063                let mut input_device_fut = input_device.flush();
1064                assert_matches!(
1065                    executor.run_until_stalled(&mut input_device_fut),
1066                    Poll::Ready(Ok(()))
1067                );
1068            }
1069        }
1070
1071        mod yields_err_if_peer_closed_device_channel_without_calling_get_input_reports_reader {
1072            use super::*;
1073            use assert_matches::assert_matches;
1074
1075            #[test]
1076            fn if_reports_were_available() {
1077                let mut executor = fasync::TestExecutor::new();
1078                let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1079                input_device
1080                    .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1081                    .expect("queuing input report");
1082
1083                let mut input_device_fut = input_device.flush();
1084                std::mem::drop(input_device_proxy);
1085                assert_matches!(
1086                    executor.run_until_stalled(&mut input_device_fut),
1087                    Poll::Ready(Err(_))
1088                )
1089            }
1090
1091            #[test]
1092            fn even_if_no_reports_were_available() {
1093                let mut executor = fasync::TestExecutor::new();
1094                let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1095                let mut input_device_fut = input_device.flush();
1096                std::mem::drop(input_device_proxy);
1097                assert_matches!(
1098                    executor.run_until_stalled(&mut input_device_fut),
1099                    Poll::Ready(Err(_))
1100                )
1101            }
1102        }
1103
1104        mod is_pending_if_peer_has_device_channel_open_and_has_not_called_get_input_reports_reader {
1105            use super::*;
1106            use assert_matches::assert_matches;
1107
1108            #[test]
1109            fn if_reports_were_available() {
1110                let mut executor = fasync::TestExecutor::new();
1111                let (_input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1112                input_device
1113                    .key_press(KeyboardReport { pressed_keys: vec![] }, DEFAULT_REPORT_TIMESTAMP)
1114                    .expect("queuing input report");
1115
1116                let mut input_device_fut = input_device.flush();
1117                assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1118            }
1119
1120            #[test]
1121            fn even_if_no_reports_were_available() {
1122                let mut executor = fasync::TestExecutor::new();
1123                let (_input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1124                let mut input_device_fut = input_device.flush();
1125                assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1126            }
1127
1128            #[test]
1129            fn even_if_get_device_descriptor_has_been_called() {
1130                let mut executor = fasync::TestExecutor::new();
1131                let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1132                let mut input_device_fut = input_device.flush();
1133                let _get_descriptor_fut = input_device_proxy.get_descriptor();
1134                assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1135            }
1136        }
1137
1138        mod is_pending_if_unacknowledged_reports_reach_limit {
1139            use super::utils::make_input_reports_reader_proxy_with_limit;
1140            use super::*;
1141            use assert_matches::assert_matches;
1142
1143            #[test]
1144            fn if_device_request_channel_is_open() {
1145                let mut executor = fasync::TestExecutor::new();
1146                let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1147                let _input_reports_reader_proxy =
1148                    make_input_reports_reader_proxy_with_limit(&input_device_proxy, 1);
1149                for _ in 0..2 {
1150                    input_device
1151                        .key_press(
1152                            KeyboardReport { pressed_keys: vec![] },
1153                            DEFAULT_REPORT_TIMESTAMP,
1154                        )
1155                        .expect("queuing input report");
1156                }
1157
1158                let mut input_device_fut = input_device.flush();
1159                assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1160            }
1161
1162            #[test]
1163            fn even_if_device_request_channel_is_closed() {
1164                let mut executor = fasync::TestExecutor::new();
1165                let (input_device_proxy, mut input_device) = make_input_device_proxy_and_struct();
1166                let _input_reports_reader_proxy =
1167                    make_input_reports_reader_proxy_with_limit(&input_device_proxy, 1);
1168                for _ in 0..2 {
1169                    input_device
1170                        .key_press(
1171                            KeyboardReport { pressed_keys: vec![] },
1172                            DEFAULT_REPORT_TIMESTAMP,
1173                        )
1174                        .expect("queuing input report");
1175                }
1176
1177                let mut input_device_fut = input_device.flush();
1178                std::mem::drop(input_device_proxy); // Terminate `InputDeviceRequestStream`.
1179                assert_matches!(executor.run_until_stalled(&mut input_device_fut), Poll::Pending)
1180            }
1181        }
1182    }
1183
1184    // Because `input_synthesis` is a library, unsupported use cases should yield `Error`s,
1185    // rather than panic!()-ing.
1186    mod unsupported_use_cases {
1187        use super::utils::make_input_device_proxy_and_struct;
1188        use super::*;
1189        use assert_matches::assert_matches;
1190
1191        #[fasync::run_until_stalled(test)]
1192        async fn multiple_get_input_reports_reader_requests_yield_error() -> Result<(), Error> {
1193            let (input_device_proxy, input_device) = make_input_device_proxy_and_struct();
1194
1195            let (_input_reports_reader_proxy, input_reports_reader_server_end) =
1196                endpoints::create_proxy::<InputReportsReaderV2Marker>();
1197            let _ = input_device_proxy
1198                .get_input_reports_reader_v2(input_reports_reader_server_end, 120);
1199
1200            let (_input_reports_reader_proxy, input_reports_reader_server_end) =
1201                endpoints::create_proxy::<InputReportsReaderV2Marker>();
1202            let _ = input_device_proxy
1203                .get_input_reports_reader_v2(input_reports_reader_server_end, 120);
1204
1205            let input_device_fut = input_device.flush();
1206            assert_matches!(input_device_fut.await, Err(_));
1207            Ok(())
1208        }
1209    }
1210
1211    mod utils {
1212        use super::*;
1213        use fidl_fuchsia_input_report::{
1214            InputDeviceProxy, InputReportsReaderV2Event, InputReportsReaderV2Proxy,
1215        };
1216
1217        /// Creates a `DeviceDescriptor` for a keyboard which has the keys enumerated
1218        /// in `keys`.
1219        pub(super) fn make_keyboard_descriptor(keys: Vec<Key>) -> DeviceDescriptor {
1220            DeviceDescriptor {
1221                keyboard: Some(KeyboardDescriptor {
1222                    input: Some(KeyboardInputDescriptor {
1223                        keys3: Some(keys),
1224                        ..Default::default()
1225                    }),
1226                    ..Default::default()
1227                }),
1228                ..Default::default()
1229            }
1230        }
1231
1232        /// Creates an `InputDeviceProxy`, for sending `fuchsia.input.report.InputDevice`
1233        /// requests, and an `InputDevice` struct that will receive the FIDL requests
1234        /// from the `InputDeviceProxy`.
1235        ///
1236        /// # Returns
1237        /// A tuple of the proxy and struct. The struct is `Box`-ed so that the caller
1238        /// can easily invoke `flush()`.
1239        pub(super) fn make_input_device_proxy_and_struct() -> (InputDeviceProxy, Box<InputDevice>) {
1240            let (input_device_proxy, input_device_request_stream) =
1241                endpoints::create_proxy_and_stream::<InputDeviceMarker>();
1242            let input_device = Box::new(InputDevice::new(
1243                input_device_request_stream,
1244                DeviceDescriptor::default(),
1245            ));
1246            (input_device_proxy, input_device)
1247        }
1248
1249        /// Creates an `InputReportsReaderV2Proxy`, for sending
1250        /// `fuchsia.input.report.InputReportsReaderV2` requests, and registers that
1251        /// `InputReportsReaderV2` with the `InputDevice` bound to `InputDeviceProxy`.
1252        ///
1253        /// # Returns
1254        /// The newly created `InputReportsReaderV2Proxy`.
1255        pub(super) fn make_input_reports_reader_proxy(
1256            input_device_proxy: &InputDeviceProxy,
1257        ) -> InputReportsReaderV2Proxy {
1258            make_input_reports_reader_proxy_with_limit(input_device_proxy, 120)
1259        }
1260
1261        pub(super) fn make_input_reports_reader_proxy_with_limit(
1262            input_device_proxy: &InputDeviceProxy,
1263            limit: u16,
1264        ) -> InputReportsReaderV2Proxy {
1265            let (input_reports_reader_proxy, input_reports_reader_server_end) =
1266                endpoints::create_proxy::<InputReportsReaderV2Marker>();
1267            let _ = input_device_proxy
1268                .get_input_reports_reader_v2(input_reports_reader_server_end, limit);
1269            input_reports_reader_proxy
1270        }
1271
1272        /// Serves `fuchsia.input.report.InputDevice` and `fuchsia.input.report.InputReportsReaderV2`
1273        /// protocols using `input_device`, and reads `InputReport`s with `InputReportsReaderV2EventStream`.
1274        /// Then drops the connections to `fuchsia.input.report.InputDevice` and `fuchsia.input.report.InputReportsReaderV2`.
1275        ///
1276        /// # Returns
1277        /// The reports provided by the `InputDevice`.
1278        pub(super) async fn get_input_reports(
1279            input_device: Box<InputDevice>,
1280            input_device_proxy: InputDeviceProxy,
1281        ) -> Vec<InputReport> {
1282            let input_reports_reader_proxy = make_input_reports_reader_proxy(&input_device_proxy);
1283            let mut event_stream = input_reports_reader_proxy.take_event_stream();
1284            let input_device_server_fut = input_device.flush();
1285            let read_reports_fut = async {
1286                let mut reports = Vec::new();
1287                while let Some(Ok(InputReportsReaderV2Event::OnInputReports {
1288                    reports: batch,
1289                    last_report_stamp,
1290                })) = event_stream.next().await
1291                {
1292                    let _ = input_reports_reader_proxy.acknowledge_reports(last_report_stamp);
1293                    reports.extend(batch);
1294                }
1295                reports
1296            };
1297            std::mem::drop(input_device_proxy); // Terminate `input_device_request_stream`.
1298            let (flush_res, reports) =
1299                future::join(input_device_server_fut, read_reports_fut).await;
1300            flush_res.expect("flush error");
1301            reports
1302        }
1303    }
1304}