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