1use crate::input_device::{self, Handled, InputDeviceBinding, InputDeviceStatus, InputEvent};
6use crate::metrics;
7use anyhow::{format_err, Error};
8use async_trait::async_trait;
9use fidl_fuchsia_input_report::{
10 self as fidl_input_report, ConsumerControlButton, InputDeviceProxy, InputReport,
11};
12use fuchsia_inspect::health::Reporter;
13use fuchsia_inspect::ArrayProperty;
14
15use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
16use metrics_registry::*;
17
18#[derive(Clone, Debug, PartialEq)]
30pub struct ConsumerControlsEvent {
31 pub pressed_buttons: Vec<ConsumerControlButton>,
32}
33
34impl ConsumerControlsEvent {
35 pub fn new(pressed_buttons: Vec<ConsumerControlButton>) -> Self {
40 Self { pressed_buttons }
41 }
42
43 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
44 let pressed_buttons_node =
45 node.create_string_array("pressed_buttons", self.pressed_buttons.len());
46 self.pressed_buttons.iter().enumerate().for_each(|(i, &ref button)| {
47 let button_name: String = match button {
48 ConsumerControlButton::VolumeUp => "volume_up".into(),
49 ConsumerControlButton::VolumeDown => "volume_down".into(),
50 ConsumerControlButton::Pause => "pause".into(),
51 ConsumerControlButton::FactoryReset => "factory_reset".into(),
52 ConsumerControlButton::MicMute => "mic_mute".into(),
53 ConsumerControlButton::Reboot => "reboot".into(),
54 ConsumerControlButton::CameraDisable => "camera_disable".into(),
55 ConsumerControlButton::Power => "power".into(),
56 ConsumerControlButton::Function => "function".into(),
57 unknown_value => {
58 format!("unknown({:?})", unknown_value)
59 }
60 };
61 pressed_buttons_node.set(i, &button_name);
62 });
63 node.record(pressed_buttons_node);
64 }
65}
66
67pub struct ConsumerControlsBinding {
74 event_sender: UnboundedSender<input_device::InputEvent>,
76
77 device_descriptor: ConsumerControlsDeviceDescriptor,
79}
80
81#[derive(Clone, Debug, Eq, PartialEq)]
82pub struct ConsumerControlsDeviceDescriptor {
83 pub buttons: Vec<ConsumerControlButton>,
85 pub device_id: u32,
87}
88
89#[async_trait]
90impl input_device::InputDeviceBinding for ConsumerControlsBinding {
91 fn input_event_sender(&self) -> UnboundedSender<input_device::InputEvent> {
92 self.event_sender.clone()
93 }
94
95 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
96 input_device::InputDeviceDescriptor::ConsumerControls(self.device_descriptor.clone())
97 }
98}
99
100impl ConsumerControlsBinding {
101 pub async fn new(
116 device_proxy: InputDeviceProxy,
117 device_id: u32,
118 input_event_sender: UnboundedSender<input_device::InputEvent>,
119 device_node: fuchsia_inspect::Node,
120 metrics_logger: metrics::MetricsLogger,
121 ) -> Result<Self, Error> {
122 let (device_binding, mut inspect_status) =
123 Self::bind_device(&device_proxy, device_id, input_event_sender, device_node).await?;
124 inspect_status.health_node.set_ok();
125 input_device::initialize_report_stream(
126 device_proxy,
127 device_binding.get_device_descriptor(),
128 device_binding.input_event_sender(),
129 inspect_status,
130 metrics_logger,
131 Self::process_reports,
132 );
133
134 Ok(device_binding)
135 }
136
137 async fn bind_device(
149 device: &InputDeviceProxy,
150 device_id: u32,
151 input_event_sender: UnboundedSender<input_device::InputEvent>,
152 device_node: fuchsia_inspect::Node,
153 ) -> Result<(Self, InputDeviceStatus), Error> {
154 let mut input_device_status = InputDeviceStatus::new(device_node);
155 let device_descriptor: fidl_input_report::DeviceDescriptor = match device
156 .get_descriptor()
157 .await
158 {
159 Ok(descriptor) => descriptor,
160 Err(_) => {
161 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
162 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
163 }
164 };
165
166 let consumer_controls_descriptor = device_descriptor.consumer_control.ok_or_else(|| {
167 input_device_status
168 .health_node
169 .set_unhealthy("DeviceDescriptor does not have a ConsumerControlDescriptor.");
170 format_err!("DeviceDescriptor does not have a ConsumerControlDescriptor")
171 })?;
172
173 let consumer_controls_input_descriptor =
174 consumer_controls_descriptor.input.ok_or_else(|| {
175 input_device_status.health_node.set_unhealthy(
176 "ConsumerControlDescriptor does not have a ConsumerControlInputDescriptor.",
177 );
178 format_err!(
179 "ConsumerControlDescriptor does not have a ConsumerControlInputDescriptor"
180 )
181 })?;
182
183 let device_descriptor: ConsumerControlsDeviceDescriptor =
184 ConsumerControlsDeviceDescriptor {
185 buttons: consumer_controls_input_descriptor.buttons.unwrap_or_default(),
186 device_id,
187 };
188
189 Ok((
190 ConsumerControlsBinding { event_sender: input_event_sender, device_descriptor },
191 input_device_status,
192 ))
193 }
194
195 fn process_reports(
216 report: InputReport,
217 previous_report: Option<InputReport>,
218 device_descriptor: &input_device::InputDeviceDescriptor,
219 input_event_sender: &mut UnboundedSender<input_device::InputEvent>,
220 inspect_status: &InputDeviceStatus,
221 metrics_logger: &metrics::MetricsLogger,
222 ) -> (Option<InputReport>, Option<UnboundedReceiver<InputEvent>>) {
223 inspect_status.count_received_report(&report);
224 let pressed_buttons: Vec<ConsumerControlButton> = match report.consumer_control {
226 Some(ref consumer_control_report) => consumer_control_report
227 .pressed_buttons
228 .as_ref()
229 .map(|buttons| buttons.iter().cloned().collect())
230 .unwrap_or_default(),
231 None => {
232 inspect_status.count_filtered_report();
233 return (previous_report, None);
234 }
235 };
236
237 send_consumer_controls_event(
238 pressed_buttons,
239 device_descriptor,
240 input_event_sender,
241 inspect_status,
242 metrics_logger,
243 );
244
245 (Some(report), None)
246 }
247}
248
249fn send_consumer_controls_event(
257 pressed_buttons: Vec<ConsumerControlButton>,
258 device_descriptor: &input_device::InputDeviceDescriptor,
259 sender: &mut UnboundedSender<input_device::InputEvent>,
260 inspect_status: &InputDeviceStatus,
261 metrics_logger: &metrics::MetricsLogger,
262) {
263 let event = input_device::InputEvent {
264 device_event: input_device::InputDeviceEvent::ConsumerControls(ConsumerControlsEvent::new(
265 pressed_buttons,
266 )),
267 device_descriptor: device_descriptor.clone(),
268 event_time: zx::MonotonicInstant::get(),
269 handled: Handled::No,
270 trace_id: None,
271 };
272
273 match sender.unbounded_send(event.clone()) {
274 Err(e) => metrics_logger.log_error(
275 InputPipelineErrorMetricDimensionEvent::ConsumerControlsSendEventFailed,
276 std::format!("Failed to send ConsumerControlsEvent with error: {:?}", e),
277 ),
278 _ => inspect_status.count_generated_event(event),
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285 use crate::testing_utilities;
286 use fuchsia_async as fasync;
287 use futures::StreamExt;
288
289 #[fasync::run_singlethreaded(test)]
292 async fn volume_up_only() {
293 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
294 let pressed_buttons = vec![ConsumerControlButton::VolumeUp];
295 let first_report = testing_utilities::create_consumer_control_input_report(
296 pressed_buttons.clone(),
297 event_time_i64,
298 );
299 let descriptor = testing_utilities::consumer_controls_device_descriptor();
300
301 let input_reports = vec![first_report];
302 let expected_events = vec![testing_utilities::create_consumer_controls_event(
303 pressed_buttons,
304 event_time_u64,
305 &descriptor,
306 )];
307
308 assert_input_report_sequence_generates_events!(
309 input_reports: input_reports,
310 expected_events: expected_events,
311 device_descriptor: descriptor,
312 device_type: ConsumerControlsBinding,
313 );
314 }
315
316 #[fasync::run_singlethreaded(test)]
319 async fn volume_up_and_down() {
320 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
321 let pressed_buttons =
322 vec![ConsumerControlButton::VolumeUp, ConsumerControlButton::VolumeDown];
323 let first_report = testing_utilities::create_consumer_control_input_report(
324 pressed_buttons.clone(),
325 event_time_i64,
326 );
327 let descriptor = testing_utilities::consumer_controls_device_descriptor();
328
329 let input_reports = vec![first_report];
330 let expected_events = vec![testing_utilities::create_consumer_controls_event(
331 pressed_buttons,
332 event_time_u64,
333 &descriptor,
334 )];
335
336 assert_input_report_sequence_generates_events!(
337 input_reports: input_reports,
338 expected_events: expected_events,
339 device_descriptor: descriptor,
340 device_type: ConsumerControlsBinding,
341 );
342 }
343
344 #[fasync::run_singlethreaded(test)]
347 async fn sequence_of_buttons() {
348 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
349 let first_report = testing_utilities::create_consumer_control_input_report(
350 vec![ConsumerControlButton::VolumeUp],
351 event_time_i64,
352 );
353 let second_report = testing_utilities::create_consumer_control_input_report(
354 vec![ConsumerControlButton::VolumeDown],
355 event_time_i64,
356 );
357 let third_report = testing_utilities::create_consumer_control_input_report(
358 vec![ConsumerControlButton::CameraDisable],
359 event_time_i64,
360 );
361 let descriptor = testing_utilities::consumer_controls_device_descriptor();
362
363 let input_reports = vec![first_report, second_report, third_report];
364 let expected_events = vec![
365 testing_utilities::create_consumer_controls_event(
366 vec![ConsumerControlButton::VolumeUp],
367 event_time_u64,
368 &descriptor,
369 ),
370 testing_utilities::create_consumer_controls_event(
371 vec![ConsumerControlButton::VolumeDown],
372 event_time_u64,
373 &descriptor,
374 ),
375 testing_utilities::create_consumer_controls_event(
376 vec![ConsumerControlButton::CameraDisable],
377 event_time_u64,
378 &descriptor,
379 ),
380 ];
381
382 assert_input_report_sequence_generates_events!(
383 input_reports: input_reports,
384 expected_events: expected_events,
385 device_descriptor: descriptor,
386 device_type: ConsumerControlsBinding,
387 );
388 }
389}