1use crate::input_device::{self, Handled, InputDeviceBinding, InputDeviceStatus, InputEvent};
6use crate::{Transport, metrics, utils};
7use anyhow::{Error, format_err};
8use async_trait::async_trait;
9use fidl_fuchsia_input_report::ConsumerControlButton;
10use fidl_next_fuchsia_input_report::InputReport;
11use fuchsia_inspect::ArrayProperty;
12use fuchsia_inspect::health::Reporter;
13
14use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
15use metrics_registry::*;
16
17#[derive(Debug)]
29pub struct ConsumerControlsEvent {
30 pub pressed_buttons: Vec<ConsumerControlButton>,
31 pub wake_lease: Option<zx::EventPair>,
32}
33
34impl Clone for ConsumerControlsEvent {
35 fn clone(&self) -> Self {
36 log::debug!("ConsumerControlsEvent cloned without wake lease.");
37 Self { pressed_buttons: self.pressed_buttons.clone(), wake_lease: None }
38 }
39}
40
41impl PartialEq for ConsumerControlsEvent {
42 fn eq(&self, other: &Self) -> bool {
43 self.pressed_buttons == other.pressed_buttons
44 && self.wake_lease.as_ref().map(|h| h.koid())
45 == other.wake_lease.as_ref().map(|h| h.koid())
46 }
47}
48
49impl Drop for ConsumerControlsEvent {
50 fn drop(&mut self) {
51 log::debug!("ConsumerControlsEvent dropped, had_wake_lease: {:?}", self.wake_lease);
52 }
53}
54
55impl ConsumerControlsEvent {
56 pub fn new(
61 pressed_buttons: Vec<ConsumerControlButton>,
62 wake_lease: Option<zx::EventPair>,
63 ) -> Self {
64 Self { pressed_buttons, wake_lease }
65 }
66
67 pub fn clone_with_wake_lease(&self) -> Self {
68 log::debug!("ConsumerControlsEvent cloned with wake lease: {:?}", self.wake_lease);
69 Self {
70 pressed_buttons: self.pressed_buttons.clone(),
71 wake_lease: self.wake_lease.as_ref().map(|lease| {
72 lease
73 .duplicate_handle(zx::Rights::SAME_RIGHTS)
74 .expect("failed to duplicate event pair")
75 }),
76 }
77 }
78
79 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
80 let pressed_buttons_node =
81 node.create_string_array("pressed_buttons", self.pressed_buttons.len());
82 self.pressed_buttons.iter().enumerate().for_each(|(i, button)| {
83 let button_name: String = match button {
84 ConsumerControlButton::VolumeUp => "volume_up".into(),
85 ConsumerControlButton::VolumeDown => "volume_down".into(),
86 ConsumerControlButton::Pause => "pause".into(),
87 ConsumerControlButton::FactoryReset => "factory_reset".into(),
88 ConsumerControlButton::MicMute => "mic_mute".into(),
89 ConsumerControlButton::Reboot => "reboot".into(),
90 ConsumerControlButton::CameraDisable => "camera_disable".into(),
91 ConsumerControlButton::Power => "power".into(),
92 ConsumerControlButton::Function => "function".into(),
93 unknown_value => {
94 format!("unknown({:?})", unknown_value)
95 }
96 };
97 pressed_buttons_node.set(i, &button_name);
98 });
99 node.record(pressed_buttons_node);
100 }
101}
102
103pub struct ConsumerControlsBinding {
110 event_sender: UnboundedSender<Vec<InputEvent>>,
112
113 device_descriptor: ConsumerControlsDeviceDescriptor,
115}
116
117#[derive(Clone, Debug, Eq, PartialEq)]
118pub struct ConsumerControlsDeviceDescriptor {
119 pub buttons: Vec<ConsumerControlButton>,
121 pub device_id: u32,
123}
124
125#[async_trait]
126impl input_device::InputDeviceBinding for ConsumerControlsBinding {
127 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
128 self.event_sender.clone()
129 }
130
131 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
132 input_device::InputDeviceDescriptor::ConsumerControls(self.device_descriptor.clone())
133 }
134}
135
136impl ConsumerControlsBinding {
137 pub async fn new(
152 device_proxy: fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
153 device_id: u32,
154 input_event_sender: UnboundedSender<Vec<InputEvent>>,
155 device_node: fuchsia_inspect::Node,
156 feature_flags: input_device::InputPipelineFeatureFlags,
157 metrics_logger: metrics::MetricsLogger,
158 ) -> Result<Self, Error> {
159 let (device_binding, mut inspect_status) =
160 Self::bind_device(&device_proxy, device_id, input_event_sender, device_node).await?;
161 inspect_status.health_node.set_ok();
162 input_device::initialize_report_stream(
163 device_proxy,
164 device_binding.get_device_descriptor(),
165 device_binding.input_event_sender(),
166 inspect_status,
167 metrics_logger,
168 feature_flags,
169 Self::process_reports,
170 );
171
172 Ok(device_binding)
173 }
174
175 async fn bind_device(
187 device: &fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
188 device_id: u32,
189 input_event_sender: UnboundedSender<Vec<InputEvent>>,
190 device_node: fuchsia_inspect::Node,
191 ) -> Result<(Self, InputDeviceStatus), Error> {
192 let mut input_device_status = InputDeviceStatus::new(device_node);
193 let device_descriptor: fidl_next_fuchsia_input_report::DeviceDescriptor = match device
194 .get_descriptor()
195 .await
196 {
197 Ok(descriptor) => descriptor.descriptor,
198 Err(_) => {
199 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
200 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
201 }
202 };
203
204 let consumer_controls_descriptor = device_descriptor.consumer_control.ok_or_else(|| {
205 input_device_status
206 .health_node
207 .set_unhealthy("DeviceDescriptor does not have a ConsumerControlDescriptor.");
208 format_err!("DeviceDescriptor does not have a ConsumerControlDescriptor")
209 })?;
210
211 let consumer_controls_input_descriptor =
212 consumer_controls_descriptor.input.ok_or_else(|| {
213 input_device_status.health_node.set_unhealthy(
214 "ConsumerControlDescriptor does not have a ConsumerControlInputDescriptor.",
215 );
216 format_err!(
217 "ConsumerControlDescriptor does not have a ConsumerControlInputDescriptor"
218 )
219 })?;
220
221 let device_descriptor: ConsumerControlsDeviceDescriptor =
222 ConsumerControlsDeviceDescriptor {
223 buttons: consumer_controls_input_descriptor
224 .buttons
225 .unwrap_or_default()
226 .into_iter()
227 .map(|b| utils::consumer_control_button_to_old(&b))
228 .collect(),
229 device_id,
230 };
231
232 Ok((
233 ConsumerControlsBinding { event_sender: input_event_sender, device_descriptor },
234 input_device_status,
235 ))
236 }
237
238 fn process_reports(
261 reports: &[fidl_next_fuchsia_input_report::wire::InputReport<'_>],
262 mut previous_report: Option<InputReport>,
263 device_descriptor: &input_device::InputDeviceDescriptor,
264 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
265 inspect_status: &InputDeviceStatus,
266 metrics_logger: &metrics::MetricsLogger,
267 _feature_flags: &input_device::InputPipelineFeatureFlags,
268 ) -> (Option<InputReport>, Option<UnboundedReceiver<InputEvent>>) {
269 fuchsia_trace::duration!("input", "consumer-controls-binding-process-report", "num_reports" => reports.len());
270 for report in reports {
271 previous_report = Self::process_report(
272 report,
273 previous_report,
274 device_descriptor,
275 input_event_sender,
276 inspect_status,
277 metrics_logger,
278 );
279 }
280 (previous_report, None)
281 }
282
283 fn process_report(
284 report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
285 previous_report: Option<InputReport>,
286 device_descriptor: &input_device::InputDeviceDescriptor,
287 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
288 inspect_status: &InputDeviceStatus,
289 metrics_logger: &metrics::MetricsLogger,
290 ) -> Option<InputReport> {
291 if let Some(trace_id) = report.trace_id() {
292 fuchsia_trace::flow_end!("input", "input_report", trace_id.0.into());
293 }
294
295 let wake_lease = utils::duplicate_wake_lease(report.wake_lease());
299
300 inspect_status.count_received_report_wire(report);
301 let pressed_buttons: Vec<ConsumerControlButton> = match report.consumer_control() {
303 Some(ref consumer_control_report) => consumer_control_report
304 .pressed_buttons()
305 .map(|buttons| {
306 buttons
307 .iter()
308 .map(|&b| {
309 let natural_button = fidl_next::FromWire::from_wire(b);
310 utils::consumer_control_button_to_old(&natural_button)
311 })
312 .collect()
313 })
314 .unwrap_or_default(),
315 None => {
316 inspect_status.count_filtered_report();
317 return previous_report;
318 }
319 };
320
321 let trace_id = fuchsia_trace::Id::new();
322 fuchsia_trace::flow_begin!("input", "event_in_input_pipeline", trace_id);
323
324 send_consumer_controls_event(
325 pressed_buttons,
326 wake_lease,
327 device_descriptor,
328 input_event_sender,
329 inspect_status,
330 metrics_logger,
331 trace_id,
332 );
333
334 let natural_report = utils::input_report_to_natural(report);
335 Some(natural_report)
336 }
337}
338
339fn send_consumer_controls_event(
349 pressed_buttons: Vec<ConsumerControlButton>,
350 wake_lease: Option<zx::EventPair>,
351 device_descriptor: &input_device::InputDeviceDescriptor,
352 sender: &mut UnboundedSender<Vec<input_device::InputEvent>>,
353 inspect_status: &InputDeviceStatus,
354 metrics_logger: &metrics::MetricsLogger,
355 trace_id: fuchsia_trace::Id,
356) {
357 let event = input_device::InputEvent {
358 device_event: input_device::InputDeviceEvent::ConsumerControls(ConsumerControlsEvent::new(
359 pressed_buttons,
360 wake_lease,
361 )),
362 device_descriptor: device_descriptor.clone(),
363 event_time: zx::MonotonicInstant::get(),
364 handled: Handled::No,
365 trace_id: Some(trace_id),
366 };
367 let events = vec![event];
368 inspect_status.count_generated_events(&events);
369
370 if let Err(e) = sender.unbounded_send(events) {
371 metrics_logger.log_error(
372 InputPipelineErrorMetricDimensionEvent::ConsumerControlsSendEventFailed,
373 std::format!("Failed to send ConsumerControlsEvent with error: {:?}", e),
374 );
375 }
376}
377
378#[cfg(test)]
379mod tests {
380 use super::*;
381 use crate::testing_utilities;
382 use fuchsia_async as fasync;
383 use futures::StreamExt;
384
385 #[fasync::run_singlethreaded(test)]
388 async fn volume_up_only() {
389 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
390 let pressed_buttons = vec![ConsumerControlButton::VolumeUp];
391 let first_report = testing_utilities::create_consumer_control_input_report(
392 pressed_buttons.clone(),
393 event_time_i64,
394 );
395 let descriptor = testing_utilities::consumer_controls_device_descriptor();
396
397 let input_reports = vec![first_report];
398 let expected_events = vec![testing_utilities::create_consumer_controls_event(
399 pressed_buttons,
400 event_time_u64,
401 &descriptor,
402 )];
403
404 assert_input_report_sequence_generates_events!(
405 input_reports: input_reports,
406 expected_events: expected_events,
407 device_descriptor: descriptor,
408 device_type: ConsumerControlsBinding,
409 );
410 }
411
412 #[fasync::run_singlethreaded(test)]
415 async fn volume_up_and_down() {
416 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
417 let pressed_buttons =
418 vec![ConsumerControlButton::VolumeUp, ConsumerControlButton::VolumeDown];
419 let first_report = testing_utilities::create_consumer_control_input_report(
420 pressed_buttons.clone(),
421 event_time_i64,
422 );
423 let descriptor = testing_utilities::consumer_controls_device_descriptor();
424
425 let input_reports = vec![first_report];
426 let expected_events = vec![testing_utilities::create_consumer_controls_event(
427 pressed_buttons,
428 event_time_u64,
429 &descriptor,
430 )];
431
432 assert_input_report_sequence_generates_events!(
433 input_reports: input_reports,
434 expected_events: expected_events,
435 device_descriptor: descriptor,
436 device_type: ConsumerControlsBinding,
437 );
438 }
439
440 #[fasync::run_singlethreaded(test)]
443 async fn sequence_of_buttons() {
444 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
445 let first_report = testing_utilities::create_consumer_control_input_report(
446 vec![ConsumerControlButton::VolumeUp],
447 event_time_i64,
448 );
449 let second_report = testing_utilities::create_consumer_control_input_report(
450 vec![ConsumerControlButton::VolumeDown],
451 event_time_i64,
452 );
453 let third_report = testing_utilities::create_consumer_control_input_report(
454 vec![ConsumerControlButton::CameraDisable],
455 event_time_i64,
456 );
457 let descriptor = testing_utilities::consumer_controls_device_descriptor();
458
459 let input_reports = vec![first_report, second_report, third_report];
460 let expected_events = vec![
461 testing_utilities::create_consumer_controls_event(
462 vec![ConsumerControlButton::VolumeUp],
463 event_time_u64,
464 &descriptor,
465 ),
466 testing_utilities::create_consumer_controls_event(
467 vec![ConsumerControlButton::VolumeDown],
468 event_time_u64,
469 &descriptor,
470 ),
471 testing_utilities::create_consumer_controls_event(
472 vec![ConsumerControlButton::CameraDisable],
473 event_time_u64,
474 &descriptor,
475 ),
476 ];
477
478 assert_input_report_sequence_generates_events!(
479 input_reports: input_reports,
480 expected_events: expected_events,
481 device_descriptor: descriptor,
482 device_type: ConsumerControlsBinding,
483 );
484 }
485}