1use async_utils::event::Event as AsyncEvent;
6use fidl_fuchsia_input::Key;
7use fidl_fuchsia_input_injection::InputDeviceRegistryMarker;
8use fidl_fuchsia_input_report::{
9 ConsumerControlInputReport, ContactInputReport, DeviceInformation, InputReport,
10 KeyboardInputReport, MouseInputReport, TouchInputReport,
11};
12use fidl_fuchsia_ui_input::KeyboardReport;
13use fidl_fuchsia_ui_test_input::{
14 CoordinateUnit, KeyboardMarker, KeyboardRequest, KeyboardRequestStream,
15 MediaButtonsDeviceMarker, MediaButtonsDeviceRequest, MediaButtonsDeviceRequestStream,
16 MouseMarker, MouseRequest, MouseRequestStream,
17 RegistryRegisterKeyboardAndGetDeviceInfoResponse,
18 RegistryRegisterMediaButtonsDeviceAndGetDeviceInfoResponse,
19 RegistryRegisterMouseAndGetDeviceInfoResponse,
20 RegistryRegisterTouchScreenAndGetDeviceInfoResponse, RegistryRequest, RegistryRequestStream,
21 TouchScreenMarker, TouchScreenRequest, TouchScreenRequestStream,
22};
23use fuchsia_component::client::connect_to_protocol;
24use fuchsia_trace::Scope;
25use futures::stream::FuturesUnordered;
26use futures::{StreamExt, TryStreamExt};
27use keymaps::inverse_keymap::{InverseKeymap, Shift};
28use keymaps::usages::{Usages, hid_usage_to_input3_key};
29use log::{error, info, warn};
30use std::time::Duration;
31use zx::HandleBased;
32use {
33 fidl_fuchsia_math as math, fidl_fuchsia_power_system as fps, fidl_fuchsia_time_alarms as fta,
34 fidl_fuchsia_ui_display_singleton as display_info, fuchsia_async as fasync, zx,
35};
36
37mod input_device;
38mod input_device_registry;
39mod input_reports_reader;
40
41pub(crate) static INPUT_CATEGORY: &str = "input";
42
43fn new_fake_device_info() -> DeviceInformation {
45 DeviceInformation {
46 product_id: Some(42),
47 vendor_id: Some(43),
48 version: Some(u32::MAX),
49 polling_rate: Some(1000),
50 ..Default::default()
51 }
52}
53
54fn derive_key_sequence(keymap: &keymaps::Keymap<'_>, input: &str) -> Option<Vec<KeyboardReport>> {
80 let inverse_keymap = InverseKeymap::new(keymap);
81 let mut reports = vec![];
82 let mut shift_pressed = false;
83 let mut last_usage = None;
84
85 for ch in input.chars() {
86 let key_stroke = inverse_keymap.get(&ch)?;
87
88 match key_stroke.shift {
89 Shift::Yes if !shift_pressed => {
90 shift_pressed = true;
91 last_usage = Some(0);
92 }
93 Shift::No if shift_pressed => {
94 shift_pressed = false;
95 last_usage = Some(0);
96 }
97 _ => {
98 if last_usage == Some(key_stroke.usage) {
99 last_usage = Some(0);
100 }
101 }
102 }
103
104 if let Some(0) = last_usage {
105 reports.push(KeyboardReport {
106 pressed_keys: if shift_pressed {
107 vec![Usages::HidUsageKeyLeftShift as u32]
108 } else {
109 vec![]
110 },
111 });
112 }
113
114 last_usage = Some(key_stroke.usage);
115
116 reports.push(KeyboardReport {
117 pressed_keys: if shift_pressed {
118 vec![key_stroke.usage, Usages::HidUsageKeyLeftShift as u32]
119 } else {
120 vec![key_stroke.usage]
121 },
122 });
123 }
124
125 reports.push(KeyboardReport { pressed_keys: vec![] });
126
127 Some(reports)
128}
129
130fn convert_keyboard_report_to_keys(report: &KeyboardReport) -> Vec<Key> {
131 report
132 .pressed_keys
133 .iter()
134 .map(|&usage| {
135 hid_usage_to_input3_key(usage.try_into().expect("failed to convert usage to u16"))
136 .unwrap_or_else(|| panic!("no Key for usage {:?}", usage))
137 })
138 .collect()
139}
140
141async fn register_touch_screen(
142 mut registry: input_device_registry::InputDeviceRegistry,
143 task_group: &mut fasync::TaskGroup,
144 device_server_end: fidl::endpoints::ServerEnd<TouchScreenMarker>,
145 got_input_reports_reader: AsyncEvent,
146 min_x: i64,
147 max_x: i64,
148 min_y: i64,
149 max_y: i64,
150) -> input_device::DeviceId {
151 let device = registry
152 .add_touchscreen_device(min_x, max_x, min_y, max_y)
153 .await
154 .expect("failed to create fake touchscreen device");
155 let device_id = device.device_id;
156
157 task_group.spawn(async move {
158 handle_touchscreen_request_stream(device, device_server_end.into_stream()).await;
159 });
160
161 info!("wait for input-pipeline setup input-reader");
162 let _ = got_input_reports_reader.wait().await;
163 info!("input-pipeline setup input-reader.");
164
165 device_id
166}
167
168async fn register_media_button(
169 mut registry: input_device_registry::InputDeviceRegistry,
170 task_group: &mut fasync::TaskGroup,
171 device_server_end: fidl::endpoints::ServerEnd<MediaButtonsDeviceMarker>,
172 got_input_reports_reader: AsyncEvent,
173) -> input_device::DeviceId {
174 let device = registry
175 .add_media_buttons_device()
176 .await
177 .expect("failed to create fake media buttons device");
178 let device_id = device.device_id;
179
180 let activity_governor = connect_to_protocol::<fps::ActivityGovernorMarker>().ok();
181 let wake_alarm_proxy = connect_to_protocol::<fta::WakeAlarmsMarker>().ok();
182 task_group.spawn(async move {
183 handle_media_buttons_device_request_stream(
184 device,
185 device_server_end.into_stream(),
186 activity_governor,
187 wake_alarm_proxy,
188 )
189 .await;
190 });
191
192 info!("wait for input-pipeline setup input-reader");
193 let _ = got_input_reports_reader.wait().await;
194 info!("input-pipeline setup input-reader.");
195
196 device_id
197}
198
199async fn register_keyboard(
200 mut registry: input_device_registry::InputDeviceRegistry,
201 task_group: &mut fasync::TaskGroup,
202 device_server_end: fidl::endpoints::ServerEnd<KeyboardMarker>,
203 got_input_reports_reader: AsyncEvent,
204) -> input_device::DeviceId {
205 let device = registry.add_keyboard_device().await.expect("failed to create fake keyboard");
206 let device_id = device.device_id;
207
208 task_group.spawn(async move {
209 handle_keyboard_request_stream(device, device_server_end.into_stream()).await;
210 });
211
212 info!("wait for input-pipeline setup input-reader");
213 let _ = got_input_reports_reader.wait().await;
214 info!("input-pipeline setup input-reader.");
215
216 device_id
217}
218
219async fn register_mouse(
220 mut registry: input_device_registry::InputDeviceRegistry,
221 task_group: &mut fasync::TaskGroup,
222 device_server_end: fidl::endpoints::ServerEnd<MouseMarker>,
223 got_input_reports_reader: AsyncEvent,
224) -> input_device::DeviceId {
225 let device = registry.add_mouse_device().await.expect("failed to create fake mouse");
226 let device_id = device.device_id;
227
228 task_group.spawn(async move {
229 handle_mouse_request_stream(device, device_server_end.into_stream()).await;
230 });
231
232 info!("wait for input-pipeline setup input-reader");
233 let _ = got_input_reports_reader.wait().await;
234 info!("input-pipeline setup input-reader.");
235
236 device_id
237}
238
239pub async fn handle_registry_request_stream(request_stream: RegistryRequestStream) {
241 request_stream
242 .try_for_each_concurrent(None, |request| async {
243 let input_device_registry = connect_to_protocol::<InputDeviceRegistryMarker>()
244 .expect("connect to input_device_registry");
245 let got_input_reports_reader = AsyncEvent::new();
246
247 let registry = input_device_registry::InputDeviceRegistry::new(
248 input_device_registry,
249 got_input_reports_reader.clone(),
250 );
251 let mut task_group = fasync::TaskGroup::new();
252
253 match request {
254 RegistryRequest::RegisterTouchScreen { payload, responder, .. } => {
255 info!("register touchscreen");
256 let device = payload
257 .device
258 .expect("no touchscreen device provided in registration request");
259 let (min_x, max_x, min_y, max_y) = match payload.coordinate_unit {
260 Some(CoordinateUnit::PhysicalPixels) => {
261 let display_info_proxy =
262 connect_to_protocol::<display_info::InfoMarker>()
263 .expect("failed to connect to display info service");
264 let display_dimensions = display_info_proxy
265 .get_metrics()
266 .await
267 .expect("failed to get display metrics")
268 .extent_in_px
269 .expect("display metrics missing extent in px");
270 (
271 0,
272 display_dimensions.width as i64,
273 0,
274 display_dimensions.height as i64,
275 )
276 }
277 Some(CoordinateUnit::RegisteredDimensions) => {
278 let dimensions =
279 payload.display_dimensions.expect("missing dimensions");
280 if dimensions.min_x >= dimensions.max_x
281 || dimensions.min_y >= dimensions.max_y
282 {
283 panic!("invalid dimensions");
284 }
285 (dimensions.min_x, dimensions.max_x, dimensions.min_y, dimensions.max_y)
286 }
287 _ => (-1000, 1000, -1000, 1000),
288 };
289
290 register_touch_screen(
291 registry,
292 &mut task_group,
293 device,
294 got_input_reports_reader,
295 min_x,
296 max_x,
297 min_y,
298 max_y,
299 )
300 .await;
301
302 responder.send().expect("Failed to respond to RegisterTouchScreen request");
303 }
304 RegistryRequest::RegisterTouchScreenAndGetDeviceInfo {
305 payload, responder, ..
306 } => {
307 info!("register touchscreen");
308 let device = payload
309 .device
310 .expect("no touchscreen device provided in registration request");
311 let (min_x, max_x, min_y, max_y) = match payload.coordinate_unit {
312 Some(CoordinateUnit::PhysicalPixels) => {
313 let display_info_proxy =
314 connect_to_protocol::<display_info::InfoMarker>()
315 .expect("failed to connect to display info service");
316 let display_dimensions = display_info_proxy
317 .get_metrics()
318 .await
319 .expect("failed to get display metrics")
320 .extent_in_px
321 .expect("display metrics missing extent in px");
322 (
323 0,
324 display_dimensions.width as i64,
325 0,
326 display_dimensions.height as i64,
327 )
328 }
329 Some(CoordinateUnit::RegisteredDimensions) => {
330 let dimensions =
331 payload.display_dimensions.expect("missing dimensions");
332 if dimensions.min_x >= dimensions.max_x
333 || dimensions.min_y >= dimensions.max_y
334 {
335 panic!("invalid dimensions");
336 }
337 (dimensions.min_x, dimensions.max_x, dimensions.min_y, dimensions.max_y)
338 }
339 _ => (-1000, 1000, -1000, 1000),
340 };
341
342 let device_id = register_touch_screen(
343 registry,
344 &mut task_group,
345 device,
346 got_input_reports_reader,
347 min_x,
348 max_x,
349 min_y,
350 max_y,
351 )
352 .await;
353
354 responder
355 .send(RegistryRegisterTouchScreenAndGetDeviceInfoResponse {
356 device_id: Some(device_id),
357 ..Default::default()
358 })
359 .expect("Failed to respond to RegisterTouchScreenAndGetDeviceInfo request");
360 }
361 RegistryRequest::RegisterMediaButtonsDevice { payload, responder, .. } => {
362 info!("register media buttons device");
363 let device = payload
364 .device
365 .expect("no media buttons device provided in registration request");
366
367 register_media_button(
368 registry,
369 &mut task_group,
370 device,
371 got_input_reports_reader,
372 )
373 .await;
374
375 responder
376 .send()
377 .expect("Failed to respond to RegisterMediaButtonsDevice request");
378 }
379 RegistryRequest::RegisterMediaButtonsDeviceAndGetDeviceInfo {
380 payload,
381 responder,
382 ..
383 } => {
384 info!("register media buttons device");
385 let device = payload
386 .device
387 .expect("no media buttons device provided in registration request");
388
389 let device_id = register_media_button(
390 registry,
391 &mut task_group,
392 device,
393 got_input_reports_reader,
394 )
395 .await;
396
397 responder.send(RegistryRegisterMediaButtonsDeviceAndGetDeviceInfoResponse {
398 device_id: Some(device_id),
399 ..Default::default()
400 }).expect(
401 "Failed to respond to RegisterMediaButtonsDeviceAndGetDeviceInfo request",
402 );
403 }
404 RegistryRequest::RegisterKeyboard { payload, responder, .. } => {
405 info!("register keyboard device");
406 let device = payload
407 .device
408 .expect("no keyboard device provided in registration request");
409
410 register_keyboard(registry, &mut task_group, device, got_input_reports_reader)
411 .await;
412
413 responder.send().expect("Failed to respond to RegisterKeyboard request");
414 }
415 RegistryRequest::RegisterKeyboardAndGetDeviceInfo {
416 payload, responder, ..
417 } => {
418 info!("register keyboard device");
419 let device = payload
420 .device
421 .expect("no keyboard device provided in registration request");
422
423 let device_id = register_keyboard(
424 registry,
425 &mut task_group,
426 device,
427 got_input_reports_reader,
428 )
429 .await;
430
431 responder
432 .send(RegistryRegisterKeyboardAndGetDeviceInfoResponse {
433 device_id: Some(device_id),
434 ..Default::default()
435 })
436 .expect("Failed to respond to RegisterKeyboardAndGetDeviceInfo request");
437 }
438 RegistryRequest::RegisterMouse { payload, responder } => {
439 info!("register mouse device");
440 let device = payload.device.expect("no mouse provided in registration request");
441
442 register_mouse(registry, &mut task_group, device, got_input_reports_reader)
443 .await;
444
445 responder.send().expect("Failed to respond to RegisterMouse request");
446 }
447 RegistryRequest::RegisterMouseAndGetDeviceInfo { payload, responder } => {
448 info!("register mouse device");
449 let device = payload.device.expect("no mouse provided in registration request");
450
451 let device_id =
452 register_mouse(registry, &mut task_group, device, got_input_reports_reader)
453 .await;
454
455 responder
456 .send(RegistryRegisterMouseAndGetDeviceInfoResponse {
457 device_id: Some(device_id),
458 ..Default::default()
459 })
460 .expect("Failed to respond to RegisterMouse request");
461 }
462 }
463
464 task_group.join().await;
465 Ok(())
466 })
467 .await
468 .expect("failed to serve test realm factory request stream");
469}
470
471fn input_report_for_touch_contacts(
472 contacts: Vec<(u32, math::Vec_)>,
473 trace_id: Option<u64>,
474) -> InputReport {
475 let contact_input_reports = contacts
476 .into_iter()
477 .map(|(contact_id, location)| ContactInputReport {
478 contact_id: Some(contact_id),
479 position_x: Some(location.x as i64),
480 position_y: Some(location.y as i64),
481 contact_width: Some(0),
482 contact_height: Some(0),
483 ..Default::default()
484 })
485 .collect();
486
487 let touch_input_report = TouchInputReport {
488 contacts: Some(contact_input_reports),
489 pressed_buttons: Some(vec![]),
490 ..Default::default()
491 };
492
493 InputReport {
494 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
495 touch: Some(touch_input_report),
496 trace_id,
497 ..Default::default()
498 }
499}
500
501async fn handle_touchscreen_request_stream(
503 touchscreen_device: input_device::InputDevice,
504 mut request_stream: TouchScreenRequestStream,
505) {
506 while let Some(request) = request_stream.next().await {
507 match request {
508 Ok(TouchScreenRequest::SimulateTap { payload, responder }) => {
509 let tap_location = payload.tap_location.expect("missing tap location");
510 {
511 fuchsia_trace::duration!("input", "simulate_tap_down");
512 let trace_id = fuchsia_trace::Id::random();
513 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
514 touchscreen_device
515 .send_input_report(input_report_for_touch_contacts(
516 vec![(1, tap_location)],
517 Some(trace_id.into()),
518 ))
519 .expect("Failed to send touch down input report");
520 }
521
522 fuchsia_trace::duration!("input", "simulate_tap_up");
525 let trace_id = fuchsia_trace::Id::random();
526 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
527 touchscreen_device
528 .send_input_report(input_report_for_touch_contacts(
529 vec![],
530 Some(trace_id.into()),
531 ))
532 .expect("failed to send touch up input report");
533
534 responder.send().expect("Failed to send SimulateTap response");
535 }
536 Ok(TouchScreenRequest::SimulateSwipe { payload, responder }) => {
537 let start_location = payload.start_location.expect("missing start location");
539 let end_location = payload.end_location.expect("missing end location");
540 let move_event_count = payload.move_event_count.expect("missing move event count");
541 assert_ne!(move_event_count, 0);
542 let duration_nanos = payload.duration.unwrap_or(0);
543 let delay_nanos = duration_nanos / ((move_event_count as i64) + 1);
544 let delay = fasync::MonotonicDuration::from_nanos(delay_nanos);
545
546 let start_x_f = start_location.x as f64;
547 let start_y_f = start_location.y as f64;
548 let end_x_f = end_location.x as f64;
549 let end_y_f = end_location.y as f64;
550 let move_event_count_f = move_event_count as f64;
551 let step_size_x = (end_x_f - start_x_f) / move_event_count_f;
552 let step_size_y = (end_y_f - start_y_f) / move_event_count_f;
553
554 for i in 0..move_event_count + 1 {
557 let i_f = i as f64;
558 let event_x = start_x_f + (i_f * step_size_x);
559 let event_y = start_y_f + (i_f * step_size_y);
560
561 {
562 fuchsia_trace::duration!("input", "simulate_swipe_move", "idx"=>i);
563 let trace_id = fuchsia_trace::Id::random();
564 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
565
566 touchscreen_device
567 .send_input_report(input_report_for_touch_contacts(
568 vec![(1, math::Vec_ { x: event_x as i32, y: event_y as i32 })],
569 Some(trace_id.into()),
570 ))
571 .expect("Failed to send tap input report");
572 }
573 fasync::Timer::new(delay).await;
574 }
575
576 fuchsia_trace::duration!("input", "simulate_swipe_up");
579 let trace_id = fuchsia_trace::Id::random();
580 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
581 touchscreen_device
582 .send_input_report(input_report_for_touch_contacts(
583 vec![],
584 Some(trace_id.into()),
585 ))
586 .expect("failed to send empty input report");
587
588 responder.send().expect("Failed to send SimulateSwipe response");
589 }
590 Ok(TouchScreenRequest::SimulateMultiTap { payload, responder }) => {
591 let tap_locations = payload.tap_locations.expect("missing tap locations");
592
593 {
594 fuchsia_trace::duration!("input", "simulate_multi_tap_down");
595 let trace_id = fuchsia_trace::Id::random();
596 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
597 touchscreen_device
598 .send_input_report(input_report_for_touch_contacts(
599 tap_locations
600 .into_iter()
601 .enumerate()
602 .map(|(i, it)| (i as u32, it))
603 .collect(),
604 Some(trace_id.into()),
605 ))
606 .expect("Failed to send tap input report");
607 }
608
609 fuchsia_trace::duration!("input", "simulate_multi_tap_up");
612 let trace_id = fuchsia_trace::Id::random();
613 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
614 touchscreen_device
615 .send_input_report(input_report_for_touch_contacts(
616 vec![],
617 Some(trace_id.into()),
618 ))
619 .expect("failed to send empty input report");
620 responder.send().expect("Failed to send SimulateMultiTap response");
621 }
622 Ok(TouchScreenRequest::SimulateMultiFingerGesture { payload, responder }) => {
623 let start_locations = payload.start_locations.expect("missing start locations");
625 let end_locations = payload.end_locations.expect("missing end locations");
626 let move_event_count = payload.move_event_count.expect("missing move event count");
627 let finger_count = payload.finger_count.expect("missing finger count") as usize;
628
629 let move_event_count_f = move_event_count as f32;
630
631 let mut steps: Vec<math::VecF> = vec![];
632
633 for finger in 0..finger_count {
634 let start_x = start_locations[finger].x as f32;
635 let start_y = start_locations[finger].y as f32;
636 let end_x = end_locations[finger].x as f32;
637 let end_y = end_locations[finger].y as f32;
638 let step_x = (end_x - start_x) / move_event_count_f;
639 let step_y = (end_y - start_y) / move_event_count_f;
640 steps.push(math::VecF { x: step_x, y: step_y });
641 }
642
643 for i in 0..move_event_count {
646 let i_f = i as f32;
647
648 let mut contacts: Vec<(u32, math::Vec_)> = vec![];
649
650 for finger in 0..finger_count {
651 let start_x = start_locations[finger].x as f32;
652 let start_y = start_locations[finger].y as f32;
653 let event_x = (start_x + i_f * steps[finger].x) as i32;
654 let event_y = (start_y + i_f * steps[finger].y) as i32;
655 contacts.push((finger as u32, math::Vec_ { x: event_x, y: event_y }));
656 }
657
658 fuchsia_trace::duration!("input", "simulate_multi_finger_gesture_move", "idx"=>i);
659 let trace_id = fuchsia_trace::Id::random();
660 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
661
662 touchscreen_device
663 .send_input_report(input_report_for_touch_contacts(
664 contacts,
665 Some(trace_id.into()),
666 ))
667 .expect("Failed to send tap input report");
668 }
669
670 fuchsia_trace::duration!("input", "simulate_multi_finger_gesture_up");
673 let trace_id = fuchsia_trace::Id::random();
674 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
675 touchscreen_device
676 .send_input_report(input_report_for_touch_contacts(
677 vec![],
678 Some(trace_id.into()),
679 ))
680 .expect("failed to send empty input report");
681
682 responder.send().expect("Failed to send SimulateMultiFingerGesture response");
683 }
684 Ok(TouchScreenRequest::SimulateTouchEvent { report, responder }) => {
685 fuchsia_trace::duration!("input", "simulate_touch_event");
686 let trace_id = fuchsia_trace::Id::random();
687 fuchsia_trace::flow_begin!("input", "input_report", trace_id);
688 let input_report = InputReport {
689 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
690 touch: Some(report),
691 trace_id: Some(trace_id.into()),
692 ..Default::default()
693 };
694 touchscreen_device
695 .send_input_report(input_report)
696 .expect("failed to send empty input report");
697 responder.send().expect("Failed to send SimulateTouchEvent response");
698 }
699 Err(e) => {
700 error!("Error on touchscreen channel: {}", e);
701 return;
702 }
703 }
704 }
705}
706
707async fn handle_media_buttons_device_request_stream(
709 media_buttons_device: input_device::InputDevice,
710 request_stream: MediaButtonsDeviceRequestStream,
711 activity_governor: Option<fps::ActivityGovernorProxy>,
712 wake_alarm_proxy: Option<fta::WakeAlarmsProxy>,
713) {
714 let mut request_stream = request_stream.fuse();
715 let (alarm_sender, mut alarm_receiver) = futures::channel::mpsc::unbounded();
716
717 let mut scheduled_inputs = FuturesUnordered::new();
719
720 loop {
721 futures::select! {
722 request = request_stream.next() => {
723 match request {
724 Some(Ok(MediaButtonsDeviceRequest::SimulateButtonPress { payload, responder })) => {
725 if let Some(button) = payload.button {
726 let wake_lease = if let Some(ref ag) = activity_governor {
727 acquire_and_deposit_lease(ag, "input-helper-button").await
728 } else {
729 None
730 };
731 send_media_button_press_and_release(&media_buttons_device, button, wake_lease);
732 responder.send().expect("Failed to send SimulateButtonPress response");
733 } else {
734 warn!("SimulateButtonPress request missing button");
735 let _ = responder.send();
736 }
737 }
738 Some(Ok(MediaButtonsDeviceRequest::SendButtonsState { payload, responder })) => {
739 let buttons = match payload.buttons {
740 Some(buttons) => buttons,
741 None => vec![],
742 };
743 let wake_lease = if let Some(ref ag) = activity_governor {
744 acquire_and_deposit_lease(ag, "input-helper-button-state").await
745 } else {
746 None
747 };
748 let input_report = InputReport {
749 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
750 consumer_control: Some(ConsumerControlInputReport {
751 pressed_buttons: Some(buttons),
752 ..Default::default()
753 }),
754 wake_lease,
755 ..Default::default()
756 };
757
758 media_buttons_device
759 .send_input_report(input_report)
760 .expect("Failed to send button press input report");
761
762 responder.send().expect("Failed to send SimulateButtonPress response");
763 }
764
765 Some(Ok(MediaButtonsDeviceRequest::ScheduleSimulateButtonPress { payload, responder })) => {
766 let button = payload.button.expect("missing button");
767 let delay = zx::Duration::from_nanos(payload.delay.expect("missing delay"));
768 let sender = alarm_sender.clone();
769 let proxy = wake_alarm_proxy.clone();
770
771 scheduled_inputs.push(
772 fasync::Task::local(async move {
773 if let Some(alarm_proxy) = proxy {
774 let time = zx::BootInstant::after(delay);
777 info!("scheduling button press for {:?}", time);
778 fuchsia_trace::instant!(
779 INPUT_CATEGORY,
780 "WakeupTest:TimerSet",
781 Scope::Process
782 );
783 let (_lease, peer) = zx::EventPair::create();
784 match alarm_proxy
785 .set_and_wait(time, fta::SetMode::KeepAlive(peer), "input_helper_button")
786 .await
787 {
788 Ok(Ok(lease_token)) => {
789 let _ = sender.unbounded_send(Some((button, lease_token)));
790 }
791 Ok(Err(e)) => {
792 error!("Failed to set wakeup alarm: {:?}", e);
793 }
794 Err(e) => {
795 error!("FIDL error: {:?}", e);
796 }
797 }
798 } else {
799 error!("failed to connect to WakeAlarms protocol");
800 }
801 }));
802 responder.send().expect("Failed to send ScheduleSimulateButtonPress response");
803 }
804 Some(Err(e)) => {
805 error!("Error on media buttons device channel: {}", e);
806 break;
807 }
808 None => break,
809 }
810 },
811 fired_alarm = alarm_receiver.next() => {
814 if let Some(Some((button, lease_token))) = fired_alarm {
815 info!("wake alarm fired, sending button event");
816 fuchsia_trace::duration!(INPUT_CATEGORY,"WakeupTest:OnTimer");
819
820 if let Ok(local_lease) = lease_token.duplicate_handle(zx::Rights::SAME_RIGHTS) {
822 deposit_wake_lease(local_lease, zx::MonotonicDuration::from_millis(100));
823 }
824
825 send_media_button_press_and_release(&media_buttons_device, button, Some(lease_token));
826 }
827 },
828 _ = scheduled_inputs.select_next_some() => {},
829 }
830 }
831}
832
833fn deposit_wake_lease(lease: zx::EventPair, duration: zx::MonotonicDuration) {
834 fasync::Task::local(async move {
835 fasync::Timer::new(fasync::MonotonicInstant::after(duration)).await;
836 std::mem::drop(lease);
837 })
838 .detach();
839}
840
841async fn acquire_and_deposit_lease(
843 ag: &fps::ActivityGovernorProxy,
844 name: &str,
845) -> Option<zx::EventPair> {
846 match ag.acquire_wake_lease(name).await {
847 Ok(Ok(lease)) => {
848 if let Ok(local_lease) = lease.duplicate_handle(zx::Rights::SAME_RIGHTS) {
849 deposit_wake_lease(local_lease, zx::MonotonicDuration::from_millis(100));
850 }
851 Some(lease)
852 }
853 Ok(Err(e)) => {
854 error!("Failed to acquire wake lease {name}: {:?}", e);
855 None
856 }
857 Err(e) => {
858 error!("FIDL error acquiring wake lease {name}: {:?}", e);
859 None
860 }
861 }
862}
863
864fn send_media_button_press_and_release(
865 media_buttons_device: &input_device::InputDevice,
866 button: fidl_fuchsia_input_report::ConsumerControlButton,
867 wake_lease: Option<zx::EventPair>,
868) {
869 let media_buttons_input_report =
870 ConsumerControlInputReport { pressed_buttons: Some(vec![button]), ..Default::default() };
871
872 let release_wake_lease =
873 wake_lease.as_ref().and_then(|lease| lease.duplicate(zx::Rights::SAME_RIGHTS).ok());
874
875 let input_report = InputReport {
876 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
877 consumer_control: Some(media_buttons_input_report),
878 wake_lease,
879 ..Default::default()
880 };
881
882 media_buttons_device
883 .send_input_report(input_report)
884 .expect("Failed to send button press input report");
885
886 let empty_report = InputReport {
890 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
891 consumer_control: Some(ConsumerControlInputReport {
892 pressed_buttons: Some(vec![]),
893 ..Default::default()
894 }),
895 wake_lease: release_wake_lease,
896 ..Default::default()
897 };
898
899 media_buttons_device
900 .send_input_report(empty_report)
901 .expect("Failed to send button release input report");
902}
903
904async fn handle_keyboard_request_stream(
906 keyboard_device: input_device::InputDevice,
907 mut request_stream: KeyboardRequestStream,
908) {
909 while let Some(request) = request_stream.next().await {
910 match request {
911 Ok(KeyboardRequest::SimulateUsAsciiTextEntry { payload, responder }) => {
912 if let Some(text) = payload.text {
913 let key_sequence = derive_key_sequence(&keymaps::US_QWERTY, &text)
914 .expect("Failed to derive key sequence");
915
916 let mut key_iter = key_sequence.into_iter().peekable();
917 while let Some(keyboard_report) = key_iter.next() {
918 let input_report = InputReport {
919 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
920 keyboard: Some(KeyboardInputReport {
921 pressed_keys3: Some(convert_keyboard_report_to_keys(
922 &keyboard_report,
923 )),
924 ..Default::default()
925 }),
926 ..Default::default()
927 };
928
929 keyboard_device
930 .send_input_report(input_report)
931 .expect("Failed to send key event report");
932
933 if key_iter.peek().is_some() {
934 fuchsia_async::Timer::new(Duration::from_millis(100)).await;
935 }
936 }
937
938 responder.send().expect("Failed to send SimulateTextEntry response");
939 } else {
940 warn!("SimulateTextEntry request missing text");
941 }
942 }
943 Ok(KeyboardRequest::SimulateKeyEvent { payload, responder }) => {
944 let keyboard_report = payload.report.expect("no report");
945 let input_report = InputReport {
946 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
947 keyboard: Some(keyboard_report),
948 ..Default::default()
949 };
950
951 keyboard_device
952 .send_input_report(input_report)
953 .expect("Failed to send key event report");
954
955 responder.send().expect("Failed to send SimulateKeyEvent response");
956 }
957 Ok(KeyboardRequest::SimulateKeyPress { payload, responder }) => {
958 let key_code = payload.key_code.expect("no key code");
959
960 let down_report = InputReport {
961 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
962 keyboard: Some(KeyboardInputReport {
963 pressed_keys3: Some(vec![key_code]),
964 ..Default::default()
965 }),
966 ..Default::default()
967 };
968
969 let up_report = InputReport {
970 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
971 keyboard: Some(KeyboardInputReport {
972 pressed_keys3: Some(vec![]),
973 ..Default::default()
974 }),
975 ..Default::default()
976 };
977
978 keyboard_device.send_input_report(down_report).expect("Failed to send key down");
979
980 keyboard_device.send_input_report(up_report).expect("Failed to send key up");
981
982 responder.send().expect("Failed to send SimulateKeyPress response");
983 }
984 Err(e) => {
985 error!("Error on keyboard device channel: {}", e);
986 return;
987 }
988 }
989 }
990}
991
992async fn handle_mouse_request_stream(
994 mouse_device: input_device::InputDevice,
995 mut request_stream: MouseRequestStream,
996) {
997 while let Some(request) = request_stream.next().await {
998 match request {
999 Ok(MouseRequest::SimulateMouseEvent { payload, responder }) => {
1000 let mut mouse_input_report = MouseInputReport {
1001 movement_x: payload.movement_x,
1002 movement_y: payload.movement_y,
1003 scroll_v: payload.scroll_v_detent,
1004 scroll_h: payload.scroll_h_detent,
1005 ..Default::default()
1006 };
1007 if let Some(pressed_buttons) = payload.pressed_buttons {
1008 mouse_input_report.pressed_buttons = Some(
1009 pressed_buttons
1010 .into_iter()
1011 .map(|b| {
1012 b.into_primitive()
1013 .try_into()
1014 .expect("failed to convert MouseButton to u8")
1015 })
1016 .collect(),
1017 );
1018 }
1019
1020 let input_report = InputReport {
1021 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
1022 mouse: Some(mouse_input_report),
1023 ..Default::default()
1024 };
1025
1026 mouse_device
1027 .send_input_report(input_report)
1028 .expect("Failed to send key event report");
1029
1030 responder.send().expect("Failed to send SimulateMouseEvent response");
1031 }
1032 Err(e) => {
1033 error!("Error on keyboard device channel: {}", e);
1034 return;
1035 }
1036 }
1037 }
1038}
1039
1040#[cfg(test)]
1041mod tests {
1042 use super::{
1049 KeyboardReport, Usages, derive_key_sequence, handle_media_buttons_device_request_stream,
1050 };
1051 use pretty_assertions::assert_eq;
1052
1053 macro_rules! reports {
1055 ( $( [ $( $usages:expr ),* ] ),* $( , )? ) => {
1056 Some(vec![
1057 $(
1058 KeyboardReport {
1059 pressed_keys: vec![$($usages as u32),*]
1060 }
1061 ),*
1062 ])
1063 }
1064 }
1065
1066 #[test]
1067 fn lowercase() {
1068 assert_eq!(
1069 derive_key_sequence(&keymaps::US_QWERTY, "lowercase"),
1070 reports![
1071 [Usages::HidUsageKeyL],
1072 [Usages::HidUsageKeyO],
1073 [Usages::HidUsageKeyW],
1074 [Usages::HidUsageKeyE],
1075 [Usages::HidUsageKeyR],
1076 [Usages::HidUsageKeyC],
1077 [Usages::HidUsageKeyA],
1078 [Usages::HidUsageKeyS],
1079 [Usages::HidUsageKeyE],
1080 [],
1081 ]
1082 );
1083 }
1084
1085 #[test]
1086 fn numerics() {
1087 assert_eq!(
1088 derive_key_sequence(&keymaps::US_QWERTY, "0123456789"),
1089 reports![
1090 [Usages::HidUsageKey0],
1091 [Usages::HidUsageKey1],
1092 [Usages::HidUsageKey2],
1093 [Usages::HidUsageKey3],
1094 [Usages::HidUsageKey4],
1095 [Usages::HidUsageKey5],
1096 [Usages::HidUsageKey6],
1097 [Usages::HidUsageKey7],
1098 [Usages::HidUsageKey8],
1099 [Usages::HidUsageKey9],
1100 [],
1101 ]
1102 );
1103 }
1104
1105 #[test]
1106 fn internet_text_entry() {
1107 assert_eq!(
1108 derive_key_sequence(&keymaps::US_QWERTY, "http://127.0.0.1:8080"),
1109 reports![
1110 [Usages::HidUsageKeyH],
1111 [Usages::HidUsageKeyT],
1112 [],
1113 [Usages::HidUsageKeyT],
1114 [Usages::HidUsageKeyP],
1115 [Usages::HidUsageKeyLeftShift],
1119 [Usages::HidUsageKeySemicolon, Usages::HidUsageKeyLeftShift],
1120 [],
1121 [Usages::HidUsageKeySlash],
1122 [],
1123 [Usages::HidUsageKeySlash],
1124 [Usages::HidUsageKey1],
1125 [Usages::HidUsageKey2],
1126 [Usages::HidUsageKey7],
1127 [Usages::HidUsageKeyDot],
1128 [Usages::HidUsageKey0],
1129 [Usages::HidUsageKeyDot],
1130 [Usages::HidUsageKey0],
1131 [Usages::HidUsageKeyDot],
1132 [Usages::HidUsageKey1],
1133 [Usages::HidUsageKeyLeftShift],
1134 [Usages::HidUsageKeySemicolon, Usages::HidUsageKeyLeftShift],
1135 [],
1136 [Usages::HidUsageKey8],
1137 [Usages::HidUsageKey0],
1138 [Usages::HidUsageKey8],
1139 [Usages::HidUsageKey0],
1140 [],
1141 ]
1142 );
1143 }
1144
1145 #[test]
1146 fn sentence() {
1147 assert_eq!(
1148 derive_key_sequence(&keymaps::US_QWERTY, "Hello, world!"),
1149 reports![
1150 [Usages::HidUsageKeyLeftShift],
1151 [Usages::HidUsageKeyH, Usages::HidUsageKeyLeftShift],
1152 [],
1153 [Usages::HidUsageKeyE],
1154 [Usages::HidUsageKeyL],
1155 [],
1156 [Usages::HidUsageKeyL],
1157 [Usages::HidUsageKeyO],
1158 [Usages::HidUsageKeyComma],
1159 [Usages::HidUsageKeySpace],
1160 [Usages::HidUsageKeyW],
1161 [Usages::HidUsageKeyO],
1162 [Usages::HidUsageKeyR],
1163 [Usages::HidUsageKeyL],
1164 [Usages::HidUsageKeyD],
1165 [Usages::HidUsageKeyLeftShift],
1166 [Usages::HidUsageKey1, Usages::HidUsageKeyLeftShift],
1167 [],
1168 ]
1169 );
1170 }
1171
1172 #[test]
1173 fn hold_shift() {
1174 assert_eq!(
1175 derive_key_sequence(&keymaps::US_QWERTY, "ALL'S WELL!"),
1176 reports![
1177 [Usages::HidUsageKeyLeftShift],
1178 [Usages::HidUsageKeyA, Usages::HidUsageKeyLeftShift],
1179 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1180 [Usages::HidUsageKeyLeftShift],
1181 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1182 [],
1183 [Usages::HidUsageKeyApostrophe],
1184 [Usages::HidUsageKeyLeftShift],
1185 [Usages::HidUsageKeyS, Usages::HidUsageKeyLeftShift],
1186 [Usages::HidUsageKeySpace, Usages::HidUsageKeyLeftShift],
1187 [Usages::HidUsageKeyW, Usages::HidUsageKeyLeftShift],
1188 [Usages::HidUsageKeyE, Usages::HidUsageKeyLeftShift],
1189 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1190 [Usages::HidUsageKeyLeftShift],
1191 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1192 [Usages::HidUsageKey1, Usages::HidUsageKeyLeftShift],
1193 [],
1194 ]
1195 );
1196 }
1197
1198 #[test]
1199 fn tab_and_newline() {
1200 assert_eq!(
1201 derive_key_sequence(&keymaps::US_QWERTY, "\tHello\n"),
1202 reports![
1203 [Usages::HidUsageKeyTab],
1204 [Usages::HidUsageKeyLeftShift],
1205 [Usages::HidUsageKeyH, Usages::HidUsageKeyLeftShift],
1206 [],
1207 [Usages::HidUsageKeyE],
1208 [Usages::HidUsageKeyL],
1209 [],
1210 [Usages::HidUsageKeyL],
1211 [Usages::HidUsageKeyO],
1212 [Usages::HidUsageKeyEnter],
1213 [],
1214 ]
1215 );
1216 }
1217
1218 #[fuchsia::test]
1219 async fn test_schedule_power_button_press() {
1220 use fidl_fuchsia_input_report::{ConsumerControlButton, InputReport};
1221 use fidl_fuchsia_time_alarms as fta;
1222 use fidl_fuchsia_ui_test_input::MediaButtonsDeviceMarker;
1223 use futures::{FutureExt, StreamExt};
1224
1225 let (report_sender, mut report_receiver) =
1226 futures::channel::mpsc::unbounded::<InputReport>();
1227 let input_device = crate::input_device::InputDevice::new_for_test(report_sender);
1228
1229 let (proxy, stream) =
1230 fidl::endpoints::create_proxy_and_stream::<MediaButtonsDeviceMarker>();
1231
1232 let (alarm_proxy, mut alarm_stream) =
1233 fidl::endpoints::create_proxy_and_stream::<fta::WakeAlarmsMarker>();
1234 let alarm_proxy_clone = alarm_proxy.clone();
1235
1236 let handler_fut = handle_media_buttons_device_request_stream(
1237 input_device,
1238 stream,
1239 None,
1240 Some(alarm_proxy_clone),
1241 );
1242
1243 let test_fut = async {
1244 let schedule_fut = proxy.schedule_simulate_button_press(
1245 &fidl_fuchsia_ui_test_input::MediaButtonsDeviceScheduleSimulateButtonPressRequest {
1246 button: Some(ConsumerControlButton::Power),
1247 delay: Some(zx::Duration::<zx::BootTimeline>::from_millis(750).into_nanos()), ..Default::default()
1249 },
1250 );
1251
1252 schedule_fut.await.expect("failed to schedule");
1253
1254 if let Some(Ok(fta::WakeAlarmsRequest::SetAndWait { responder, .. })) =
1256 alarm_stream.next().await
1257 {
1258 let (lease, _peer) = zx::EventPair::create();
1259 responder.send(Ok(lease)).expect("failed to respond");
1260 }
1261
1262 let press_report: InputReport = report_receiver.next().await.expect("no press report");
1264 assert!(press_report.consumer_control.is_some());
1265 let cc = press_report.consumer_control.unwrap();
1266 assert_eq!(cc.pressed_buttons, Some(vec![ConsumerControlButton::Power]));
1267 assert!(press_report.wake_lease.is_some());
1268
1269 let release_report: InputReport =
1271 report_receiver.next().await.expect("no release report");
1272 let cc = release_report.consumer_control.unwrap();
1273 assert_eq!(cc.pressed_buttons, Some(vec![]));
1274 assert!(release_report.wake_lease.is_some());
1275 };
1276
1277 futures::select! {
1278 _ = handler_fut.fuse() => panic!("handler exited early"),
1279 _ = test_fut.fuse() => (),
1280 }
1281 }
1282}