input_pipeline/light_sensor/
light_sensor_binding.rs1use super::types::Rgbc;
6use crate::input_device::{
7 self, Handled, InputDeviceBinding, InputDeviceDescriptor, InputDeviceStatus, InputEvent,
8};
9use crate::metrics;
10use anyhow::{Error, format_err};
11use async_trait::async_trait;
12use fidl_fuchsia_input_report::{InputDeviceProxy, InputReport, SensorDescriptor, SensorType};
13use fuchsia_inspect::health::Reporter;
14
15use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
16use metrics_registry::*;
17
18#[derive(Clone, Debug)]
19pub struct LightSensorEvent {
20 pub(crate) device_proxy: InputDeviceProxy,
21 pub(crate) rgbc: Rgbc<u16>,
22}
23
24impl PartialEq for LightSensorEvent {
25 fn eq(&self, other: &Self) -> bool {
26 self.rgbc == other.rgbc
27 }
28}
29
30impl Eq for LightSensorEvent {}
31
32impl LightSensorEvent {
33 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
34 node.record_uint("red", u64::from(self.rgbc.red));
35 node.record_uint("green", u64::from(self.rgbc.green));
36 node.record_uint("blue", u64::from(self.rgbc.blue));
37 node.record_uint("clear", u64::from(self.rgbc.clear));
38 }
39}
40
41pub(crate) struct LightSensorBinding {
45 event_sender: UnboundedSender<Vec<InputEvent>>,
47
48 device_descriptor: LightSensorDeviceDescriptor,
50}
51
52#[derive(Copy, Clone, Debug, Eq, PartialEq)]
53pub struct LightSensorDeviceDescriptor {
54 pub(crate) vendor_id: u32,
56
57 pub(crate) product_id: u32,
59
60 pub(crate) device_id: u32,
62
63 pub(crate) sensor_layout: Rgbc<usize>,
65}
66
67#[async_trait]
68impl InputDeviceBinding for LightSensorBinding {
69 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
70 self.event_sender.clone()
71 }
72
73 fn get_device_descriptor(&self) -> InputDeviceDescriptor {
74 InputDeviceDescriptor::LightSensor(self.device_descriptor.clone())
75 }
76}
77
78impl LightSensorBinding {
79 pub(crate) async fn new(
94 device_proxy: InputDeviceProxy,
95 device_id: u32,
96 input_event_sender: UnboundedSender<Vec<InputEvent>>,
97 device_node: fuchsia_inspect::Node,
98 feature_flags: input_device::InputPipelineFeatureFlags,
99 metrics_logger: metrics::MetricsLogger,
100 ) -> Result<Self, Error> {
101 let (device_binding, mut inspect_status) = Self::bind_device(
102 &device_proxy,
103 device_id,
104 input_event_sender,
105 device_node,
106 metrics_logger.clone(),
107 )
108 .await?;
109 inspect_status.health_node.set_ok();
110 input_device::initialize_report_stream(
111 device_proxy.clone(),
112 device_binding.get_device_descriptor(),
113 device_binding.input_event_sender(),
114 inspect_status,
115 metrics_logger,
116 feature_flags,
117 move |report,
118 previous_report,
119 device_descriptor,
120 input_event_sender,
121 inspect_status,
122 metrics_logger,
123 _feature_flags| {
124 Self::process_reports(
125 report,
126 previous_report,
127 device_descriptor,
128 input_event_sender,
129 device_proxy.clone(),
130 inspect_status,
131 metrics_logger,
132 )
133 },
134 );
135
136 Ok(device_binding)
137 }
138
139 async fn bind_device(
151 device: &InputDeviceProxy,
152 device_id: u32,
153 input_event_sender: UnboundedSender<Vec<InputEvent>>,
154 device_node: fuchsia_inspect::Node,
155 metrics_logger: metrics::MetricsLogger,
156 ) -> Result<(Self, InputDeviceStatus), Error> {
157 let mut input_device_status = InputDeviceStatus::new(device_node);
158 let descriptor = match device.get_descriptor().await {
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 let device_info = descriptor.device_information.ok_or_else(|| {
166 input_device_status.health_node.set_unhealthy("Empty device_info in descriptor.");
167 metrics_logger.log_error(
170 InputPipelineErrorMetricDimensionEvent::LightEmptyDeviceInfo,
171 std::format!("DRIVER BUG: empty device_info for device_id: {}", device_id),
172 );
173 format_err!("empty device info for device_id: {}", device_id)
174 })?;
175 match descriptor.sensor {
176 Some(SensorDescriptor { input: Some(input_descriptors), .. }) => {
177 let sensor_layout = input_descriptors
178 .into_iter()
179 .filter_map(|input_descriptor| {
180 input_descriptor.values.and_then(|values| {
181 let mut red_value = None;
182 let mut green_value = None;
183 let mut blue_value = None;
184 let mut clear_value = None;
185 for (i, value) in values.iter().enumerate() {
186 let old = match value.type_ {
187 SensorType::LightRed => {
188 std::mem::replace(&mut red_value, Some(i))
189 }
190 SensorType::LightGreen => {
191 std::mem::replace(&mut green_value, Some(i))
192 }
193 SensorType::LightBlue => {
194 std::mem::replace(&mut blue_value, Some(i))
195 }
196 SensorType::LightIlluminance => {
197 std::mem::replace(&mut clear_value, Some(i))
198 }
199 type_ => {
200 log::warn!(
201 "unexpected sensor type {type_:?} found on light \
202 sensor device"
203 );
204 None
205 }
206 };
207 if old.is_some() {
208 log::warn!(
209 "existing index for light sensor {:?} replaced",
210 value.type_
211 );
212 }
213 }
214
215 red_value.and_then(|red| {
216 green_value.and_then(|green| {
217 blue_value.and_then(|blue| {
218 clear_value.map(|clear| Rgbc { red, green, blue, clear })
219 })
220 })
221 })
222 })
223 })
224 .next()
225 .ok_or_else(|| {
226 input_device_status.health_node.set_unhealthy("Missing light sensor data.");
227 format_err!("missing sensor data in device")
228 })?;
229 Ok((
230 LightSensorBinding {
231 event_sender: input_event_sender,
232 device_descriptor: LightSensorDeviceDescriptor {
233 vendor_id: device_info.vendor_id.unwrap_or_default(),
234 product_id: device_info.product_id.unwrap_or_default(),
235 device_id,
236 sensor_layout,
237 },
238 },
239 input_device_status,
240 ))
241 }
242 device_descriptor => {
243 input_device_status
244 .health_node
245 .set_unhealthy("Light Sensor Device Descriptor failed to parse.");
246 Err(format_err!(
247 "Light Sensor Device Descriptor failed to parse: \n {:?}",
248 device_descriptor
249 ))
250 }
251 }
252 }
253
254 fn process_reports(
273 reports: Vec<InputReport>,
274 mut previous_report: Option<InputReport>,
275 device_descriptor: &input_device::InputDeviceDescriptor,
276 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
277 device_proxy: InputDeviceProxy,
278 inspect_status: &InputDeviceStatus,
279 metrics_logger: &metrics::MetricsLogger,
280 ) -> (Option<InputReport>, Option<UnboundedReceiver<InputEvent>>) {
281 fuchsia_trace::duration!("input", "light-sensor-binding-process-reports", "num_reports" => reports.len());
282 for report in reports {
283 previous_report = Self::process_report(
284 report,
285 previous_report,
286 device_descriptor,
287 input_event_sender,
288 device_proxy.clone(),
289 inspect_status,
290 metrics_logger,
291 );
292 }
293 (previous_report, None)
294 }
295
296 fn process_report(
297 report: InputReport,
298 previous_report: Option<InputReport>,
299 device_descriptor: &input_device::InputDeviceDescriptor,
300 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
301 device_proxy: InputDeviceProxy,
302 inspect_status: &InputDeviceStatus,
303 metrics_logger: &metrics::MetricsLogger,
304 ) -> Option<InputReport> {
305 if let Some(trace_id) = report.trace_id {
306 fuchsia_trace::flow_end!("input", "input_report", trace_id.into());
307 }
308
309 inspect_status.count_received_report(&report);
310 let light_sensor_descriptor =
311 if let input_device::InputDeviceDescriptor::LightSensor(light_sensor_descriptor) =
312 device_descriptor
313 {
314 light_sensor_descriptor
315 } else {
316 unreachable!()
317 };
318
319 let sensor = match &report.sensor {
321 None => {
322 inspect_status.count_filtered_report();
323 return previous_report;
324 }
325 Some(sensor) => sensor,
326 };
327
328 let values = match &sensor.values {
329 None => {
330 inspect_status.count_filtered_report();
331 return None;
332 }
333 Some(values) => values,
334 };
335
336 let event = input_device::InputEvent {
337 device_event: input_device::InputDeviceEvent::LightSensor(LightSensorEvent {
338 device_proxy,
339 rgbc: Rgbc {
340 red: values[light_sensor_descriptor.sensor_layout.red] as u16,
341 green: values[light_sensor_descriptor.sensor_layout.green] as u16,
342 blue: values[light_sensor_descriptor.sensor_layout.blue] as u16,
343 clear: values[light_sensor_descriptor.sensor_layout.clear] as u16,
344 },
345 }),
346 device_descriptor: device_descriptor.clone(),
347 event_time: zx::MonotonicInstant::get(),
348 handled: Handled::No,
349 trace_id: None,
350 };
351
352 if let Err(e) = input_event_sender.unbounded_send(vec![event.clone()]) {
353 metrics_logger.log_error(
354 InputPipelineErrorMetricDimensionEvent::LightFailedToSendEvent,
355 std::format!("Failed to send LightSensorEvent with error: {e:?}"),
356 );
357 } else {
358 inspect_status.count_generated_event(event);
359 }
360
361 Some(report)
362 }
363}