1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "chre_cross_validator_sensor_manager.h"
18 
19 #include <algorithm>
20 #include <cinttypes>
21 
22 #include <chre.h>
23 #include <pb_decode.h>
24 #include <pb_encode.h>
25 
26 #include "chre/util/nanoapp/callbacks.h"
27 #include "chre/util/nanoapp/log.h"
28 #include "chre/util/optional.h"
29 #include "chre/util/time.h"
30 #include "chre_cross_validation_sensor.nanopb.h"
31 
32 #define LOG_TAG "[ChreCrossValidator]"
33 
34 namespace chre {
35 
36 namespace cross_validator_sensor {
37 
38 namespace {
39 
decodeSensorName(pb_istream_t * stream,const pb_field_s * field,void ** arg)40 bool decodeSensorName(pb_istream_t *stream, const pb_field_s *field,
41                       void **arg) {
42   unsigned char *name = static_cast<unsigned char *>(*arg);
43 
44   if (stream->bytes_left > kMaxSensorNameSize - 1) return false;
45 
46   size_t bytesToCopy = stream->bytes_left;
47   if (!pb_read(stream, name, stream->bytes_left)) return false;
48   name[bytesToCopy] = '\0';
49 
50   return true;
51 }
52 
53 }  // namespace
54 
~Manager()55 Manager::~Manager() {
56   cleanup();
57 }
58 
cleanup()59 void Manager::cleanup() {
60   if (mCrossValidatorState.has_value()) {
61     switch (mCrossValidatorState->crossValidatorType) {
62       case CrossValidatorType::SENSOR:
63         if (!chreSensorConfigureModeOnly(mCrossValidatorState->sensorHandle,
64                                          CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
65           LOGE(
66               "Sensor cleanup failed when trying to configure sensor with "
67               "handle "
68               "%" PRIu32 " to done mode",
69               mCrossValidatorState->sensorHandle);
70         }
71         break;
72       default:
73         break;
74     }
75   }
76 }
77 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)78 void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
79                           const void *eventData) {
80   switch (eventType) {
81     case CHRE_EVENT_MESSAGE_FROM_HOST:
82       handleMessageFromHost(
83           senderInstanceId,
84           static_cast<const chreMessageFromHostData *>(eventData));
85       break;
86     // TODO(b/146052784): Check that data received from CHRE apis is the correct
87     // type for current test.
88     case CHRE_EVENT_SENSOR_ACCELEROMETER_DATA:
89       handleSensorThreeAxisData(
90           static_cast<const chreSensorThreeAxisData *>(eventData),
91           CHRE_SENSOR_TYPE_ACCELEROMETER);
92       break;
93     case CHRE_EVENT_SENSOR_GYROSCOPE_DATA:
94       handleSensorThreeAxisData(
95           static_cast<const chreSensorThreeAxisData *>(eventData),
96           CHRE_SENSOR_TYPE_GYROSCOPE);
97       break;
98     case CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA:
99       handleSensorThreeAxisData(
100           static_cast<const chreSensorThreeAxisData *>(eventData),
101           CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD);
102       break;
103     case CHRE_EVENT_SENSOR_PRESSURE_DATA:
104       handleSensorFloatData(static_cast<const chreSensorFloatData *>(eventData),
105                             CHRE_SENSOR_TYPE_PRESSURE);
106       break;
107     case CHRE_EVENT_SENSOR_LIGHT_DATA:
108       handleSensorFloatData(static_cast<const chreSensorFloatData *>(eventData),
109                             CHRE_SENSOR_TYPE_LIGHT);
110       break;
111     case CHRE_EVENT_SENSOR_PROXIMITY_DATA:
112       handleProximityData(static_cast<const chreSensorByteData *>(eventData));
113       break;
114     case CHRE_EVENT_SENSOR_STEP_COUNTER_DATA:
115       handleStepCounterData(
116           static_cast<const chreSensorUint64Data *>(eventData));
117       break;
118     case CHRE_EVENT_SENSOR_SAMPLING_CHANGE:
119       // Ignore sampling state changes
120       break;
121     default:
122       LOGE("Got unknown event type from senderInstanceId %" PRIu32
123            " and with eventType %" PRIu16,
124            senderInstanceId, eventType);
125   }
126 }
127 
encodeThreeAxisSensorDatapointValues(pb_ostream_t * stream,const pb_field_t *,void * const * arg)128 bool Manager::encodeThreeAxisSensorDatapointValues(pb_ostream_t *stream,
129                                                    const pb_field_t * /*field*/,
130                                                    void *const *arg) {
131   const auto *sensorThreeAxisDataSample = static_cast<
132       const chreSensorThreeAxisData::chreSensorThreeAxisSampleData *>(*arg);
133 
134   for (size_t i = 0; i < 3; i++) {
135     if (!pb_encode_tag_for_field(
136             stream,
137             &chre_cross_validation_sensor_SensorDatapoint_fields
138                 [chre_cross_validation_sensor_SensorDatapoint_values_tag -
139                  1])) {
140       return false;
141     }
142     if (!pb_encode_fixed32(stream, &sensorThreeAxisDataSample->values[i])) {
143       return false;
144     }
145   }
146   return true;
147 }
148 
makeDatapoint(bool (* encodeFunc)(pb_ostream_t *,const pb_field_t *,void * const *),const void * sampleDataFromChre,uint64_t currentTimestamp)149 chre_cross_validation_sensor_SensorDatapoint Manager::makeDatapoint(
150     bool (*encodeFunc)(pb_ostream_t *, const pb_field_t *, void *const *),
151     const void *sampleDataFromChre, uint64_t currentTimestamp) {
152   return chre_cross_validation_sensor_SensorDatapoint{
153       .has_timestampInNs = true,
154       .timestampInNs = currentTimestamp,
155       .values = {.funcs = {.encode = encodeFunc},
156                  .arg = const_cast<void *>(sampleDataFromChre)}};
157 }
158 
encodeFloatSensorDatapointValue(pb_ostream_t * stream,const pb_field_t *,void * const * arg)159 bool Manager::encodeFloatSensorDatapointValue(pb_ostream_t *stream,
160                                               const pb_field_t * /*field*/,
161                                               void *const *arg) {
162   const auto *sensorFloatDataSample =
163       static_cast<const chreSensorFloatData::chreSensorFloatSampleData *>(*arg);
164   if (!pb_encode_tag_for_field(
165           stream,
166           &chre_cross_validation_sensor_SensorDatapoint_fields
167               [chre_cross_validation_sensor_SensorDatapoint_values_tag - 1])) {
168     return false;
169   }
170   if (!pb_encode_fixed32(stream, &sensorFloatDataSample->value)) {
171     return false;
172   }
173   return true;
174 }
175 
encodeProximitySensorDatapointValue(pb_ostream_t * stream,const pb_field_t *,void * const * arg)176 bool Manager::encodeProximitySensorDatapointValue(pb_ostream_t *stream,
177                                                   const pb_field_t * /*field*/,
178                                                   void *const *arg) {
179   const auto *sensorFloatDataSample =
180       static_cast<const chreSensorByteData::chreSensorByteSampleData *>(*arg);
181   if (!pb_encode_tag_for_field(
182           stream,
183           &chre_cross_validation_sensor_SensorDatapoint_fields
184               [chre_cross_validation_sensor_SensorDatapoint_values_tag - 1])) {
185     return false;
186   }
187   float isNearFloat = sensorFloatDataSample->isNear ? 0.0 : 1.0;
188   if (!pb_encode_fixed32(stream, &isNearFloat)) {
189     return false;
190   }
191   return true;
192 }
193 
encodeStepCounterSensorDatapointValue(pb_ostream_t * stream,const pb_field_t * field,void * const * arg)194 bool Manager::encodeStepCounterSensorDatapointValue(pb_ostream_t *stream,
195                                                     const pb_field_t *field,
196                                                     void *const *arg) {
197   const auto *sensorUint64DataSample =
198       static_cast<const chreSensorUint64Data::chreSensorUint64SampleData *>(
199           *arg);
200   if (!pb_encode_tag_for_field(
201           stream,
202           &chre_cross_validation_sensor_SensorDatapoint_fields
203               [chre_cross_validation_sensor_SensorDatapoint_values_tag - 1])) {
204     return false;
205   }
206   // This value is casted to a float for the Java sensors framework so do it
207   // here to make it easier to encode into the existing proto message.
208   float stepValue = float(sensorUint64DataSample->value);
209   if (!pb_encode_fixed32(stream, &stepValue)) {
210     return false;
211   }
212   return true;
213 }
214 
encodeThreeAxisSensorDatapoints(pb_ostream_t * stream,const pb_field_t *,void * const * arg)215 bool Manager::encodeThreeAxisSensorDatapoints(pb_ostream_t *stream,
216                                               const pb_field_t * /*field*/,
217                                               void *const *arg) {
218   const auto *sensorThreeAxisData =
219       static_cast<const chreSensorThreeAxisData *>(*arg);
220   uint64_t currentTimestamp = sensorThreeAxisData->header.baseTimestamp +
221                               chreGetEstimatedHostTimeOffset();
222   for (size_t i = 0; i < sensorThreeAxisData->header.readingCount; i++) {
223     const chreSensorThreeAxisData::chreSensorThreeAxisSampleData &sampleData =
224         sensorThreeAxisData->readings[i];
225     currentTimestamp += sampleData.timestampDelta;
226     if (!pb_encode_tag_for_field(
227             stream,
228             &chre_cross_validation_sensor_SensorData_fields
229                 [chre_cross_validation_sensor_SensorData_datapoints_tag - 1])) {
230       return false;
231     }
232     chre_cross_validation_sensor_SensorDatapoint datapoint = makeDatapoint(
233         encodeThreeAxisSensorDatapointValues, &sampleData, currentTimestamp);
234     if (!pb_encode_submessage(
235             stream, chre_cross_validation_sensor_SensorDatapoint_fields,
236             &datapoint)) {
237       return false;
238     }
239   }
240   return true;
241 }
242 
encodeFloatSensorDatapoints(pb_ostream_t * stream,const pb_field_t *,void * const * arg)243 bool Manager::encodeFloatSensorDatapoints(pb_ostream_t *stream,
244                                           const pb_field_t * /*field*/,
245                                           void *const *arg) {
246   const auto *sensorFloatData = static_cast<const chreSensorFloatData *>(*arg);
247   uint64_t currentTimestamp =
248       sensorFloatData->header.baseTimestamp + chreGetEstimatedHostTimeOffset();
249   for (size_t i = 0; i < sensorFloatData->header.readingCount; i++) {
250     const chreSensorFloatData::chreSensorFloatSampleData &sampleData =
251         sensorFloatData->readings[i];
252     currentTimestamp += sampleData.timestampDelta;
253     if (!pb_encode_tag_for_field(
254             stream,
255             &chre_cross_validation_sensor_SensorData_fields
256                 [chre_cross_validation_sensor_SensorData_datapoints_tag - 1])) {
257       return false;
258     }
259     chre_cross_validation_sensor_SensorDatapoint datapoint = makeDatapoint(
260         encodeFloatSensorDatapointValue, &sampleData, currentTimestamp);
261     if (!pb_encode_submessage(
262             stream, chre_cross_validation_sensor_SensorDatapoint_fields,
263             &datapoint)) {
264       return false;
265     }
266   }
267   return true;
268 }
269 
encodeProximitySensorDatapoints(pb_ostream_t * stream,const pb_field_t *,void * const * arg)270 bool Manager::encodeProximitySensorDatapoints(pb_ostream_t *stream,
271                                               const pb_field_t * /*field*/,
272                                               void *const *arg) {
273   const auto *sensorProximityData =
274       static_cast<const chreSensorByteData *>(*arg);
275   uint64_t currentTimestamp = sensorProximityData->header.baseTimestamp +
276                               chreGetEstimatedHostTimeOffset();
277   for (size_t i = 0; i < sensorProximityData->header.readingCount; i++) {
278     const chreSensorByteData::chreSensorByteSampleData &sampleData =
279         sensorProximityData->readings[i];
280     currentTimestamp += sampleData.timestampDelta;
281     if (!pb_encode_tag_for_field(
282             stream,
283             &chre_cross_validation_sensor_SensorData_fields
284                 [chre_cross_validation_sensor_SensorData_datapoints_tag - 1])) {
285       return false;
286     }
287     chre_cross_validation_sensor_SensorDatapoint datapoint = makeDatapoint(
288         encodeProximitySensorDatapointValue, &sampleData, currentTimestamp);
289     if (!pb_encode_submessage(
290             stream, chre_cross_validation_sensor_SensorDatapoint_fields,
291             &datapoint)) {
292       return false;
293     }
294   }
295   return true;
296 }
297 
encodeStepCounterSensorDatapoints(pb_ostream_t * stream,const pb_field_t * field,void * const * arg)298 bool Manager::encodeStepCounterSensorDatapoints(pb_ostream_t *stream,
299                                                 const pb_field_t *field,
300                                                 void *const *arg) {
301   const auto *sensorStepCounterData =
302       static_cast<const chreSensorUint64Data *>(*arg);
303   uint64_t currentTimestamp = sensorStepCounterData->header.baseTimestamp +
304                               chreGetEstimatedHostTimeOffset();
305   for (size_t i = 0; i < sensorStepCounterData->header.readingCount; i++) {
306     const chreSensorUint64Data::chreSensorUint64SampleData &sampleData =
307         sensorStepCounterData->readings[i];
308     currentTimestamp += sampleData.timestampDelta;
309     if (!pb_encode_tag_for_field(
310             stream,
311             &chre_cross_validation_sensor_SensorData_fields
312                 [chre_cross_validation_sensor_SensorData_datapoints_tag - 1])) {
313       return false;
314     }
315     chre_cross_validation_sensor_SensorDatapoint datapoint = makeDatapoint(
316         encodeStepCounterSensorDatapointValue, &sampleData, currentTimestamp);
317     if (!pb_encode_submessage(
318             stream, chre_cross_validation_sensor_SensorDatapoint_fields,
319             &datapoint)) {
320       return false;
321     }
322   }
323   return true;
324 }
325 
handleStartSensorMessage(const chre_cross_validation_sensor_StartSensorCommand & startSensorCommand)326 bool Manager::handleStartSensorMessage(
327     const chre_cross_validation_sensor_StartSensorCommand &startSensorCommand) {
328   bool success = false;
329   uint8_t sensorType = startSensorCommand.chreSensorType;
330   uint64_t intervalFromApInNs =
331       startSensorCommand.intervalInMs * kOneMillisecondInNanoseconds;
332   uint64_t latencyInNs =
333       startSensorCommand.latencyInMs * kOneMillisecondInNanoseconds;
334   bool isContinuous = startSensorCommand.isContinuous;
335   uint32_t sensorIndex = startSensorCommand.sensorIndex;
336 
337   uint32_t handle;
338   if (!getSensor(sensorType, sensorIndex, &handle)) {
339     LOGE("Could not find default sensor for sensorType %" PRIu8
340          " index %" PRIu32,
341          sensorType, sensorIndex);
342     // TODO(b/146052784): Test other sensor configure modes
343   } else {
344     LOGI("Starting x-validation for sensor type %" PRIu8 " index %" PRIu32,
345          sensorType, sensorIndex);
346     chreSensorInfo sensorInfo;
347     if (!chreGetSensorInfo(handle, &sensorInfo)) {
348       LOGE("Error getting sensor info for sensor");
349     } else {
350       // TODO(b/154271547): Send minInterval to AP and have the AP decide from
351       // both CHRE and AP min and max interval.
352       uint64_t intervalInNs =
353           std::max(intervalFromApInNs, sensorInfo.minInterval);
354       // Copy hostEndpoint param from previous version of cross validator
355       // state
356       mCrossValidatorState = CrossValidatorState(
357           CrossValidatorType::SENSOR, sensorType, handle, chreGetTime(),
358           mCrossValidatorState->hostEndpoint, isContinuous);
359       if (!chreSensorConfigure(handle, CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS,
360                                intervalInNs, latencyInNs)) {
361         LOGE("Error configuring sensor with sensorType %" PRIu8
362              ", interval %" PRIu64 "ns, and latency %" PRIu64 "ns",
363              sensorType, intervalInNs, latencyInNs);
364       } else {
365         LOGD("Sensor with sensor type %" PRIu8 " configured", sensorType);
366         success = true;
367       }
368     }
369   }
370   return success;
371 }
372 
isValidHeader(const chreSensorDataHeader & header)373 bool Manager::isValidHeader(const chreSensorDataHeader &header) {
374   // On-change sensors may send cached values because the data value has not
375   // changed since the test started
376   bool isTimestampValid =
377       !mCrossValidatorState->isContinuous ||
378       header.baseTimestamp >= mCrossValidatorState->timeStart;
379   return header.readingCount > 0 && isTimestampValid;
380 }
381 
handleStartMessage(uint16_t hostEndpoint,const chreMessageFromHostData * hostData)382 void Manager::handleStartMessage(uint16_t hostEndpoint,
383                                  const chreMessageFromHostData *hostData) {
384   bool success = true;
385   // Default values for everything but hostEndpoint param
386   mCrossValidatorState = CrossValidatorState(CrossValidatorType::SENSOR, 0, 0,
387                                              0, hostEndpoint, false);
388   pb_istream_t istream = pb_istream_from_buffer(
389       static_cast<const pb_byte_t *>(hostData->message), hostData->messageSize);
390   chre_cross_validation_sensor_StartCommand startCommand =
391       chre_cross_validation_sensor_StartCommand_init_default;
392   if (!pb_decode(&istream, chre_cross_validation_sensor_StartCommand_fields,
393                  &startCommand)) {
394     LOGE("Could not decode start command");
395   } else {
396     switch (startCommand.which_command) {
397       case chre_cross_validation_sensor_StartCommand_startSensorCommand_tag:
398         success =
399             handleStartSensorMessage(startCommand.command.startSensorCommand);
400         break;
401       default:
402         LOGE("Unknown start command type %" PRIu8, startCommand.which_command);
403     }
404   }
405   // If error occurred in validation setup then resetting mCrossValidatorState
406   // will alert the event handler
407   if (!success) {
408     mCrossValidatorState.reset();
409   }
410 }
411 
handleInfoMessage(uint16_t hostEndpoint,const chreMessageFromHostData * hostData)412 void Manager::handleInfoMessage(uint16_t hostEndpoint,
413                                 const chreMessageFromHostData *hostData) {
414   chre_cross_validation_sensor_SensorInfoResponse infoResponse =
415       chre_cross_validation_sensor_SensorInfoResponse_init_default;
416   pb_istream_t istream = pb_istream_from_buffer(
417       static_cast<const pb_byte_t *>(hostData->message), hostData->messageSize);
418   chre_cross_validation_sensor_SensorInfoCommand infoCommand =
419       chre_cross_validation_sensor_SensorInfoCommand_init_default;
420 
421   infoCommand.sensorName.funcs.decode = decodeSensorName;
422   infoCommand.sensorName.arg = mSensorNameArray;
423 
424   if (!pb_decode(&istream,
425                  chre_cross_validation_sensor_SensorInfoCommand_fields,
426                  &infoCommand)) {
427     LOGE("Could not decode info command");
428   } else {
429     uint32_t handle;
430     infoResponse.has_chreSensorType = true;
431     infoResponse.chreSensorType = infoCommand.chreSensorType;
432     infoResponse.has_isAvailable = true;
433     infoResponse.isAvailable = false;
434     infoResponse.has_sensorIndex = false;
435 
436     bool supportsMultiSensors =
437         chreSensorFind(infoCommand.chreSensorType, 1, &handle);
438     for (uint8_t i = 0; chreSensorFind(infoCommand.chreSensorType, i, &handle);
439          i++) {
440       struct chreSensorInfo info;
441       if (!chreGetSensorInfo(handle, &info)) {
442         LOGE("Failed to get sensor info");
443       } else {
444         bool equal = true;
445         if (supportsMultiSensors) {
446           equal = (strcmp(info.sensorName, mSensorNameArray) == 0);
447           LOGI("Got sensor name %s in-name %s, equal %d", info.sensorName,
448                mSensorNameArray, equal);
449         }
450         if (equal) {
451           infoResponse.isAvailable = true;
452           infoResponse.has_sensorIndex = true;
453           infoResponse.sensorIndex = i;
454           break;
455         }
456       }
457     }
458   }
459 
460   sendInfoResponse(hostEndpoint, infoResponse);
461 }
462 
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)463 void Manager::handleMessageFromHost(uint32_t senderInstanceId,
464                                     const chreMessageFromHostData *hostData) {
465   if (senderInstanceId != CHRE_INSTANCE_ID) {
466     LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
467   } else {
468     uint16_t hostEndpoint;
469     if (hostData->hostEndpoint != CHRE_HOST_ENDPOINT_UNSPECIFIED) {
470       hostEndpoint = hostData->hostEndpoint;
471     } else {
472       hostEndpoint = CHRE_HOST_ENDPOINT_BROADCAST;
473     }
474 
475     switch (hostData->messageType) {
476       case chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_START:
477         handleStartMessage(hostEndpoint, hostData);
478         break;
479       case chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_INFO:
480         handleInfoMessage(hostEndpoint, hostData);
481         break;
482       default:
483         LOGE("Unknown message type %" PRIu32 " for host message",
484              hostData->messageType);
485     }
486   }
487 }
488 
makeSensorThreeAxisData(const chreSensorThreeAxisData * threeAxisDataFromChre,uint8_t sensorType)489 chre_cross_validation_sensor_Data Manager::makeSensorThreeAxisData(
490     const chreSensorThreeAxisData *threeAxisDataFromChre, uint8_t sensorType) {
491   chre_cross_validation_sensor_SensorData newThreeAxisData = {
492       .has_chreSensorType = true,
493       .chreSensorType = sensorType,
494       .has_accuracy = true,
495       .accuracy = threeAxisDataFromChre->header.accuracy,
496       .datapoints = {
497           .funcs = {.encode = encodeThreeAxisSensorDatapoints},
498           .arg = const_cast<chreSensorThreeAxisData *>(threeAxisDataFromChre)}};
499   chre_cross_validation_sensor_Data newData = {
500       .which_data = chre_cross_validation_sensor_Data_sensorData_tag,
501       .data =
502           {
503               .sensorData = newThreeAxisData,
504           },
505   };
506   return newData;
507 }
508 
makeSensorFloatData(const chreSensorFloatData * floatDataFromChre,uint8_t sensorType)509 chre_cross_validation_sensor_Data Manager::makeSensorFloatData(
510     const chreSensorFloatData *floatDataFromChre, uint8_t sensorType) {
511   chre_cross_validation_sensor_SensorData newfloatData = {
512       .has_chreSensorType = true,
513       .chreSensorType = sensorType,
514       .has_accuracy = true,
515       .accuracy = floatDataFromChre->header.accuracy,
516       .datapoints = {
517           .funcs = {.encode = encodeFloatSensorDatapoints},
518           .arg = const_cast<chreSensorFloatData *>(floatDataFromChre)}};
519   chre_cross_validation_sensor_Data newData = {
520       .which_data = chre_cross_validation_sensor_Data_sensorData_tag,
521       .data =
522           {
523               .sensorData = newfloatData,
524           },
525   };
526   return newData;
527 }
528 
makeSensorProximityData(const chreSensorByteData * proximityDataFromChre)529 chre_cross_validation_sensor_Data Manager::makeSensorProximityData(
530     const chreSensorByteData *proximityDataFromChre) {
531   chre_cross_validation_sensor_SensorData newProximityData = {
532       .has_chreSensorType = true,
533       .chreSensorType = CHRE_SENSOR_TYPE_PROXIMITY,
534       .has_accuracy = true,
535       .accuracy = proximityDataFromChre->header.accuracy,
536       .datapoints = {
537           .funcs = {.encode = encodeProximitySensorDatapoints},
538           .arg = const_cast<chreSensorByteData *>(proximityDataFromChre)}};
539   chre_cross_validation_sensor_Data newData = {
540       .which_data = chre_cross_validation_sensor_Data_sensorData_tag,
541       .data =
542           {
543               .sensorData = newProximityData,
544           },
545   };
546   return newData;
547 }
548 
makeSensorStepCounterData(const chreSensorUint64Data * stepCounterDataFromChre)549 chre_cross_validation_sensor_Data Manager::makeSensorStepCounterData(
550     const chreSensorUint64Data *stepCounterDataFromChre) {
551   chre_cross_validation_sensor_SensorData newStepCounterData = {
552       .has_chreSensorType = true,
553       .chreSensorType = CHRE_SENSOR_TYPE_STEP_COUNTER,
554       .has_accuracy = true,
555       .accuracy = stepCounterDataFromChre->header.accuracy,
556       .datapoints = {
557           .funcs = {.encode = encodeStepCounterSensorDatapoints},
558           .arg = const_cast<chreSensorUint64Data *>(stepCounterDataFromChre)}};
559   chre_cross_validation_sensor_Data newData = {
560       .which_data = chre_cross_validation_sensor_Data_sensorData_tag,
561       .data =
562           {
563               .sensorData = newStepCounterData,
564           },
565   };
566   return newData;
567 }
568 
handleSensorThreeAxisData(const chreSensorThreeAxisData * threeAxisDataFromChre,uint8_t sensorType)569 void Manager::handleSensorThreeAxisData(
570     const chreSensorThreeAxisData *threeAxisDataFromChre, uint8_t sensorType) {
571   if (processSensorData(threeAxisDataFromChre->header, sensorType)) {
572     chre_cross_validation_sensor_Data newData =
573         makeSensorThreeAxisData(threeAxisDataFromChre, sensorType);
574     sendDataToHost(newData);
575   }
576 }
577 
handleSensorFloatData(const chreSensorFloatData * floatDataFromChre,uint8_t sensorType)578 void Manager::handleSensorFloatData(
579     const chreSensorFloatData *floatDataFromChre, uint8_t sensorType) {
580   if (processSensorData(floatDataFromChre->header, sensorType)) {
581     chre_cross_validation_sensor_Data newData =
582         makeSensorFloatData(floatDataFromChre, sensorType);
583     sendDataToHost(newData);
584   }
585 }
586 
handleProximityData(const chreSensorByteData * proximityDataFromChre)587 void Manager::handleProximityData(
588     const chreSensorByteData *proximityDataFromChre) {
589   if (processSensorData(proximityDataFromChre->header,
590                         CHRE_SENSOR_TYPE_PROXIMITY)) {
591     chre_cross_validation_sensor_Data newData =
592         makeSensorProximityData(proximityDataFromChre);
593     sendDataToHost(newData);
594   }
595 }
596 
handleStepCounterData(const chreSensorUint64Data * stepCounterDataFromChre)597 void Manager::handleStepCounterData(
598     const chreSensorUint64Data *stepCounterDataFromChre) {
599   if (processSensorData(stepCounterDataFromChre->header,
600                         CHRE_SENSOR_TYPE_STEP_COUNTER)) {
601     chre_cross_validation_sensor_Data newData =
602         makeSensorStepCounterData(stepCounterDataFromChre);
603     sendDataToHost(newData);
604   }
605 }
606 
sendDataToHost(const chre_cross_validation_sensor_Data & data)607 void Manager::sendDataToHost(const chre_cross_validation_sensor_Data &data) {
608   sendMessageToHost(
609       mCrossValidatorState->hostEndpoint,
610       chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_DATA,
611       chre_cross_validation_sensor_Data_fields, &data);
612 }
613 
sendInfoResponse(uint16_t hostEndpoint,const chre_cross_validation_sensor_SensorInfoResponse & infoResponse)614 void Manager::sendInfoResponse(
615     uint16_t hostEndpoint,
616     const chre_cross_validation_sensor_SensorInfoResponse &infoResponse) {
617   sendMessageToHost(
618       hostEndpoint,
619       chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_INFO_RESPONSE,
620       chre_cross_validation_sensor_SensorInfoResponse_fields, &infoResponse);
621 }
622 
sendMessageToHost(uint16_t hostEndpoint,uint16_t messageType,const pb_field_t fields[],const void * srcStruct)623 void Manager::sendMessageToHost(uint16_t hostEndpoint, uint16_t messageType,
624                                 const pb_field_t fields[],
625                                 const void *srcStruct) {
626   size_t encodedSize;
627   if (!pb_get_encoded_size(&encodedSize, fields, srcStruct)) {
628     LOGE("Could not get encoded size of proto message");
629   } else {
630     pb_byte_t *buffer = static_cast<pb_byte_t *>(chreHeapAlloc(encodedSize));
631     if (buffer == nullptr) {
632       LOG_OOM();
633     } else {
634       pb_ostream_t ostream = pb_ostream_from_buffer(buffer, encodedSize);
635       if (!pb_encode(&ostream, fields, srcStruct)) {
636         LOGE("Could not encode proto message");
637       } else if (!chreSendMessageToHostEndpoint(
638                      static_cast<void *>(buffer), encodedSize, messageType,
639                      hostEndpoint, heapFreeMessageCallback)) {
640         LOGE("Could not send message to host");
641       }
642     }
643   }
644 }
645 
processSensorData(const chreSensorDataHeader & header,uint8_t sensorType)646 bool Manager::processSensorData(const chreSensorDataHeader &header,
647                                 uint8_t sensorType) {
648   if (!mCrossValidatorState.has_value()) {
649     LOGE("Start message not received or invalid when data received");
650   } else if (!isValidHeader(header)) {
651     LOGE("Invalid data being thrown away");
652   } else if (!sensorTypeIsValid(sensorType)) {
653     LOGE("Unexpected sensor data type %" PRIu8 ", expected %" PRIu8, sensorType,
654          mCrossValidatorState->sensorType);
655   } else {
656     return true;
657   }
658   return false;
659 }
660 
sensorTypeIsValid(uint8_t sensorType)661 bool Manager::sensorTypeIsValid(uint8_t sensorType) {
662   return sensorType == mCrossValidatorState->sensorType;
663 }
664 
getSensor(uint32_t sensorType,uint32_t sensorIndex,uint32_t * handle)665 bool Manager::getSensor(uint32_t sensorType, uint32_t sensorIndex,
666                         uint32_t *handle) {
667   bool success = false;
668 
669   bool supportsMultiSensor = (chreGetApiVersion() >= CHRE_API_VERSION_1_5);
670   if (sensorIndex > UINT8_MAX) {
671     LOGE("CHRE only supports max of 255 sensor indices");
672   } else if (!supportsMultiSensor && sensorIndex != 0) {
673     LOGW("CHRE API does not support multi-sensors");
674   } else {
675     success = chreSensorFind(sensorType, sensorIndex, handle);
676   }
677 
678   return success;
679 }
680 
681 }  // namespace cross_validator_sensor
682 
683 }  // namespace chre
684