1 /*
2 * Copyright (C) 2017 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/platform/slpi/see/see_helper.h"
18
19 #include "pb_decode.h"
20 #include "pb_encode.h"
21 #include "sns_cal.pb.h"
22 #include "sns_client.pb.h"
23 #include "sns_client_api_v01.h"
24 #include "sns_proximity.pb.h"
25 #include "sns_rc.h"
26 #include "sns_remote_proc_state.pb.h"
27 #include "sns_std.pb.h"
28 #include "sns_std_sensor.pb.h"
29 #include "stringl.h"
30 #include "timer.h"
31
32 #include <algorithm>
33 #include <cfloat>
34 #include <cinttypes>
35 #include <cmath>
36
37 #include "chre/platform/assert.h"
38 #include "chre/platform/log.h"
39 #include "chre/platform/slpi/system_time_util.h"
40 #include "chre/util/lock_guard.h"
41 #include "chre/util/macros.h"
42
43 #ifdef CHREX_SENSOR_SUPPORT
44 #include "chre/extensions/platform/vendor_sensor_types.h"
45 #endif // CHREX_SENSOR_SUPPORT
46
47 #define LOG_NANOPB_ERROR(stream) \
48 LOGE("Nanopb error: %s:%d", PB_GET_ERROR(stream), __LINE__)
49
50 namespace chre {
51 namespace {
52
53 //! Operating mode indicating sensor is disabled.
54 const char *kOpModeOff = "OFF";
55
56 //! The SUID of the look up sensor.
57 const sns_std_suid kSuidLookup = sns_suid_sensor_init_default;
58
59 //! A struct to facilitate SEE response handling
60 struct SeeRespCbData {
61 SeeHelper *seeHelper;
62 uint32_t txnId;
63 };
64
65 //! A struct to facilitate pb encode/decode
66 struct SeeBufArg {
67 const void *buf;
68 size_t bufLen;
69 };
70
71 //! A struct to facilitate pb decode of sync calls.
72 struct SeeSyncArg {
73 sns_std_suid syncSuid;
74 void *syncData;
75 const char *syncDataType;
76 bool syncIndFound;
77 };
78
79 //! SeeFloatArg can be used to decode a vectorized 3x3 array.
80 constexpr size_t kSeeFloatArgValLen = 9;
81
82 //! A struct to facilitate decoding a float array.
83 struct SeeFloatArg {
84 size_t index;
85 float val[kSeeFloatArgValLen];
86 };
87
88 //! A struct to facilitate pb decode of sensor data event.
89 struct SeeDataArg {
90 uint64_t prevTimeNs;
91 uint64_t timeNs;
92 size_t sampleIndex;
93 size_t totalSamples;
94 UniquePtr<uint8_t> event;
95 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData> status;
96 SeeCalData *cal;
97 SensorType sensorType;
98 bool isHostWakeSuspendEvent;
99 bool isHostAwake;
100 };
101
102 //! A struct to facilitate pb decode
103 struct SeeInfoArg {
104 sns_client *client;
105 sns_std_suid suid;
106 uint32_t msgId;
107 SeeSyncArg *sync;
108 SeeDataArg *data;
109 bool decodeMsgIdOnly;
110 Optional<sns_std_suid> *remoteProcSuid;
111 SeeCalInfo *calInfo;
112 };
113
114 //! A struct to facilitate decoding sensor attributes.
115 struct SeeAttrArg {
116 union {
117 char strVal[kSeeAttrStrValLen];
118 bool boolVal;
119 struct {
120 float fltMin;
121 float fltMax;
122 };
123 int64_t int64;
124 };
125 bool initialized;
126 };
127
getCalIndexFromSensorType(SensorType sensorType)128 size_t getCalIndexFromSensorType(SensorType sensorType) {
129 SeeCalSensor index;
130 switch (sensorType) {
131 case SensorType::Accelerometer:
132 index = SeeCalSensor::AccelCal;
133 break;
134 case SensorType::Gyroscope:
135 index = SeeCalSensor::GyroCal;
136 break;
137 case SensorType::GeomagneticField:
138 index = SeeCalSensor::MagCal;
139 break;
140 default:
141 index = SeeCalSensor::NumCalSensors;
142 }
143 return static_cast<size_t>(index);
144 }
145
getCalIndexFromDataType(const char * dataType)146 size_t getCalIndexFromDataType(const char *dataType) {
147 SensorType sensorType = SensorType::Unknown;
148 if (strcmp(dataType, "accel_cal") == 0) {
149 sensorType = SensorType::Accelerometer;
150 } else if (strcmp(dataType, "gyro_cal") == 0) {
151 sensorType = SensorType::Gyroscope;
152 } else if (strcmp(dataType, "mag_cal") == 0) {
153 sensorType = SensorType::GeomagneticField;
154 }
155 return getCalIndexFromSensorType(sensorType);
156 }
157
getCalIndexFromSuid(const sns_std_suid & suid,const SeeCalInfo * calInfo)158 size_t getCalIndexFromSuid(const sns_std_suid& suid,
159 const SeeCalInfo *calInfo) {
160 size_t i = 0;
161 for (; i < kNumSeeCalSensors; i++) {
162 if (calInfo[i].suid.has_value()
163 && suidsMatch(suid, calInfo[i].suid.value())) {
164 break;
165 }
166 }
167 return i;
168 }
169
170 /**
171 * Copy an encoded pb message to a wrapper proto's field.
172 */
copyPayload(pb_ostream_t * stream,const pb_field_t * field,void * const * arg)173 bool copyPayload(pb_ostream_t *stream, const pb_field_t *field,
174 void *const *arg) {
175 bool success = false;
176
177 auto *data = static_cast<const SeeBufArg *>(*arg);
178 if (!pb_encode_tag_for_field(stream, field)) {
179 LOG_NANOPB_ERROR(stream);
180 } else if (!pb_encode_string(
181 stream, static_cast<const pb_byte_t *>(data->buf), data->bufLen)) {
182 LOG_NANOPB_ERROR(stream);
183 } else {
184 success = true;
185 }
186 return success;
187 }
188
189 /**
190 * Encodes sns_std_attr_req pb message.
191 *
192 * @param msg A non-null pointer to the pb message unique pointer whose object
193 * will be assigned here.
194 * @param msgLen A non-null pointer to the size of the encoded pb message.
195 *
196 * @return true if the pb message and length were obtained.
197 */
encodeSnsStdAttrReq(UniquePtr<pb_byte_t> * msg,size_t * msgLen)198 bool encodeSnsStdAttrReq(UniquePtr<pb_byte_t> *msg, size_t *msgLen) {
199 CHRE_ASSERT(msg);
200 CHRE_ASSERT(msgLen);
201
202 // Initialize the pb message
203 sns_std_attr_req req = {};
204
205 bool success = pb_get_encoded_size(msgLen, sns_std_attr_req_fields, &req);
206 if (!success) {
207 LOGE("pb_get_encoded_size failed for sns_str_attr_req");
208 } else {
209 UniquePtr<pb_byte_t> buf(static_cast<pb_byte_t *>(memoryAlloc(*msgLen)));
210 *msg = std::move(buf);
211
212 // The encoded size can be 0 as there's only one optional field.
213 if (msg->isNull() && *msgLen > 0) {
214 LOG_OOM();
215 } else {
216 pb_ostream_t stream = pb_ostream_from_buffer(msg->get(), *msgLen);
217
218 success = pb_encode(&stream, sns_std_attr_req_fields, &req);
219 if (!success) {
220 LOG_NANOPB_ERROR(&stream);
221 }
222 }
223 }
224 return success;
225 }
226
227 /**
228 * Encodes sns_suid_req pb message.
229 *
230 * @param dataType Sensor data type, "accel" for example.
231 * @param msg A non-null pointer to the pb message unique pointer whose object
232 * will be assigned here.
233 * @param msgLen A non-null pointer to the size of the encoded pb message.
234 *
235 * @return true if the pb message and length were obtained.
236 */
encodeSnsSuidReq(const char * dataType,UniquePtr<pb_byte_t> * msg,size_t * msgLen)237 bool encodeSnsSuidReq(const char *dataType,
238 UniquePtr<pb_byte_t> *msg, size_t *msgLen) {
239 CHRE_ASSERT(msg);
240 CHRE_ASSERT(msgLen);
241 bool success = false;
242
243 // Initialize the pb message
244 SeeBufArg data = {
245 .buf = dataType,
246 .bufLen = strlen(dataType),
247 };
248 sns_suid_req req = {
249 .data_type.funcs.encode = copyPayload,
250 .data_type.arg = &data,
251 };
252
253 if (!pb_get_encoded_size(msgLen, sns_suid_req_fields, &req)) {
254 LOGE("pb_get_encoded_size failed for sns_suid_req: %s", dataType);
255 } else if (*msgLen == 0) {
256 LOGE("Invalid pb encoded size for sns_suid_req");
257 } else {
258 UniquePtr<pb_byte_t> buf(static_cast<pb_byte_t *>(memoryAlloc(*msgLen)));
259 *msg = std::move(buf);
260 if (msg->isNull()) {
261 LOG_OOM();
262 } else {
263 pb_ostream_t stream = pb_ostream_from_buffer(msg->get(), *msgLen);
264
265 success = pb_encode(&stream, sns_suid_req_fields, &req);
266 if (!success) {
267 LOG_NANOPB_ERROR(&stream);
268 }
269 }
270 }
271 return success;
272 }
273
274 /**
275 * Encodes sns_std_sensor_config pb message.
276 *
277 * @param request The request to be encoded.
278 * @param msg A non-null pointer to the pb message unique pointer whose object
279 * will be assigned here.
280 * @param msgLen A non-null pointer to the size of the encoded pb message.
281 *
282 * @return true if the pb message and length were obtained.
283 */
encodeSnsStdSensorConfig(const SeeSensorRequest & request,UniquePtr<pb_byte_t> * msg,size_t * msgLen)284 bool encodeSnsStdSensorConfig(const SeeSensorRequest& request,
285 UniquePtr<pb_byte_t> *msg, size_t *msgLen) {
286 CHRE_ASSERT(msg);
287 CHRE_ASSERT(msgLen);
288 bool success = false;
289
290 // Initialize the pb message
291 sns_std_sensor_config req = {
292 .sample_rate = request.samplingRateHz,
293 };
294
295 if (!pb_get_encoded_size(msgLen, sns_std_sensor_config_fields, &req)) {
296 LOGE("pb_get_encoded_size failed for sns_std_sensor_config");
297 } else if (*msgLen == 0) {
298 LOGE("Invalid pb encoded size for sns_std_sensor_config");
299 } else {
300 UniquePtr<pb_byte_t> buf(static_cast<pb_byte_t *>(memoryAlloc(*msgLen)));
301 *msg = std::move(buf);
302 if (msg->isNull()) {
303 LOG_OOM();
304 } else {
305 pb_ostream_t stream = pb_ostream_from_buffer(msg->get(), *msgLen);
306
307 success = pb_encode(&stream, sns_std_sensor_config_fields, &req);
308 if (!success) {
309 LOG_NANOPB_ERROR(&stream);
310 }
311 }
312 }
313 return success;
314 }
315
encodeSnsRemoteProcSensorConfig(pb_byte_t * msgBuffer,size_t msgBufferSize,size_t * msgLen,sns_std_client_processor processorType)316 bool encodeSnsRemoteProcSensorConfig(pb_byte_t *msgBuffer, size_t msgBufferSize,
317 size_t *msgLen,
318 sns_std_client_processor processorType) {
319 CHRE_ASSERT(msgBuffer);
320 CHRE_ASSERT(msgLen);
321
322 sns_remote_proc_state_config request = {
323 .proc_type = processorType,
324 };
325
326 pb_ostream_t stream = pb_ostream_from_buffer(msgBuffer, msgBufferSize);
327 bool success = pb_encode(
328 &stream, sns_remote_proc_state_config_fields, &request);
329 if (!success) {
330 LOG_NANOPB_ERROR(&stream);
331 } else {
332 *msgLen = stream.bytes_written;
333 }
334
335 return success;
336 }
337
338 /**
339 * Prepares a sns_client_req message with provided payload.
340 */
prepSnsClientReq(sns_std_suid suid,uint32_t msgId,void * payload,size_t payloadLen,bool batchValid,uint32_t batchPeriodUs,bool passive,UniquePtr<sns_client_request_msg> * msg,SeeBufArg * data)341 bool prepSnsClientReq(sns_std_suid suid, uint32_t msgId,
342 void *payload, size_t payloadLen,
343 bool batchValid, uint32_t batchPeriodUs, bool passive,
344 UniquePtr<sns_client_request_msg> *msg, SeeBufArg *data) {
345 CHRE_ASSERT(payload || payloadLen == 0);
346 CHRE_ASSERT(msg);
347 CHRE_ASSERT(data);
348 bool success = false;
349
350 auto req = MakeUniqueZeroFill<sns_client_request_msg>();
351 if (req.isNull()) {
352 LOG_OOM();
353 } else {
354 success = true;
355
356 // Initialize sns_client_request_msg to be sent
357 data->buf = payload,
358 data->bufLen = payloadLen,
359
360 req->suid = suid;
361 req->msg_id = msgId;
362 req->susp_config.client_proc_type = SNS_STD_CLIENT_PROCESSOR_SSC;
363 req->susp_config.delivery_type = SNS_CLIENT_DELIVERY_WAKEUP;
364 req->request.has_batching = batchValid;
365 req->request.batching.batch_period = batchPeriodUs;
366 req->request.payload.funcs.encode = copyPayload;
367 req->request.payload.arg = data;
368 req->request.has_is_passive = true,
369 req->request.is_passive = passive,
370
371 *msg = std::move(req);
372 }
373 return success;
374 }
375
376 /**
377 * Helps decode a pb string field and passes the string to the calling function.
378 */
decodeStringField(pb_istream_t * stream,const pb_field_t * field,void ** arg)379 bool decodeStringField(pb_istream_t *stream, const pb_field_t *field,
380 void **arg) {
381 auto *data = static_cast<SeeBufArg *>(*arg);
382 data->bufLen = stream->bytes_left;
383 data->buf = stream->state;
384
385 bool success = pb_read(stream, nullptr /* buf */, stream->bytes_left);
386 if (!success) {
387 LOG_NANOPB_ERROR(stream);
388 }
389 return success;
390 }
391
392 /**
393 * Decodes each SUID.
394 */
decodeSnsSuidEventSuid(pb_istream_t * stream,const pb_field_t * field,void ** arg)395 bool decodeSnsSuidEventSuid(pb_istream_t *stream, const pb_field_t *field,
396 void **arg) {
397 sns_std_suid suid = {};
398 bool success = pb_decode(stream, sns_std_suid_fields, &suid);
399 if (!success) {
400 LOG_NANOPB_ERROR(stream);
401 } else {
402 auto *suids = static_cast<DynamicVector<sns_std_suid> *>(*arg);
403 suids->push_back(suid);
404 }
405 return success;
406 }
407
decodeSnsSuidEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)408 bool decodeSnsSuidEvent(pb_istream_t *stream, const pb_field_t *field,
409 void **arg) {
410 auto *info = static_cast<SeeInfoArg *>(*arg);
411 if (!suidsMatch(info->suid, kSuidLookup)) {
412 LOGE("SNS_SUID_MSGID_SNS_SUID_EVENT with incorrect SUID: 0x%" PRIx64
413 " %" PRIx64, info->suid.suid_high, info->suid.suid_low);
414 }
415
416 SeeBufArg data;
417 DynamicVector<sns_std_suid> suids;
418 sns_suid_event event = {
419 .data_type.funcs.decode = decodeStringField,
420 .data_type.arg = &data,
421 .suid.funcs.decode = decodeSnsSuidEventSuid,
422 .suid.arg = &suids,
423 };
424
425 bool success = pb_decode(stream, sns_suid_event_fields, &event);
426 if (!success) {
427 LOG_NANOPB_ERROR(stream);
428 } else {
429 // If syncData == nullptr, this indication is received outside of a sync
430 // call. If the decoded data type doesn't match the one we are waiting
431 // for, this indication is from a previous call (may be findSuidSync)
432 // and happens to arrive between another sync req/ind pair.
433 // Note that req/ind misalignment can still happen if findSuidSync is
434 // called again with the same data type.
435 // Note that there's no need to compare the SUIDs as no other calls
436 // but findSuidSync populate mWaitingDataType and can lead to a data
437 // type match.
438 if (info->sync->syncData == nullptr
439 || strncmp(info->sync->syncDataType,
440 static_cast<const char *>(data.buf),
441 std::min(data.bufLen, kSeeAttrStrValLen)) != 0) {
442 LOGW("Received late SNS_SUID_MSGID_SNS_SUID_EVENT indication");
443 } else {
444 info->sync->syncIndFound = true;
445 auto *outputSuids = static_cast<DynamicVector<sns_std_suid> *>(
446 info->sync->syncData);
447 for (const auto& suid : suids) {
448 outputSuids->push_back(suid);
449 }
450 }
451 }
452 return success;
453 }
454
455 /**
456 * Decode messages defined in sns_suid.proto
457 */
decodeSnsSuidProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)458 bool decodeSnsSuidProtoEvent(pb_istream_t *stream, const pb_field_t *field,
459 void **arg) {
460 bool success = false;
461
462 auto *info = static_cast<SeeInfoArg *>(*arg);
463 switch (info->msgId) {
464 case SNS_SUID_MSGID_SNS_SUID_EVENT:
465 success = decodeSnsSuidEvent(stream, field, arg);
466 break;
467
468 default:
469 LOGW("Unhandled sns_suid.proto msg ID: %" PRIu32, info->msgId);
470 break;
471 }
472 return success;
473 }
474
475 /**
476 * Defined in sns_std_sensor.pb.h
477 */
getAttrNameFromAttrId(int32_t id)478 const char *getAttrNameFromAttrId(int32_t id) {
479 switch (id) {
480 case SNS_STD_SENSOR_ATTRID_NAME:
481 return "NAME";
482 case SNS_STD_SENSOR_ATTRID_VENDOR:
483 return "VENDOR";
484 case SNS_STD_SENSOR_ATTRID_TYPE:
485 return "TYPE";
486 case SNS_STD_SENSOR_ATTRID_AVAILABLE:
487 return "AVAILABLE";
488 case SNS_STD_SENSOR_ATTRID_VERSION:
489 return "VERSION";
490 case SNS_STD_SENSOR_ATTRID_API:
491 return "API";
492 case SNS_STD_SENSOR_ATTRID_RATES:
493 return "RATES";
494 case SNS_STD_SENSOR_ATTRID_RESOLUTIONS:
495 return "RESOLUTIONS";
496 case SNS_STD_SENSOR_ATTRID_FIFO_SIZE:
497 return "FIFO_SIZE";
498 case SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT:
499 return "ACTIVE_CURRENT";
500 case SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT:
501 return "SLEEP_CURRENT";
502 case SNS_STD_SENSOR_ATTRID_RANGES:
503 return "RANGES";
504 case SNS_STD_SENSOR_ATTRID_OP_MODES:
505 return "OP_MODES";
506 case SNS_STD_SENSOR_ATTRID_DRI:
507 return "DRI";
508 case SNS_STD_SENSOR_ATTRID_STREAM_SYNC:
509 return "STREAM_SYNC";
510 case SNS_STD_SENSOR_ATTRID_EVENT_SIZE:
511 return "EVENT_SIZE";
512 case SNS_STD_SENSOR_ATTRID_STREAM_TYPE:
513 return "STREAM_TYPE";
514 case SNS_STD_SENSOR_ATTRID_DYNAMIC:
515 return "DYNAMIC";
516 case SNS_STD_SENSOR_ATTRID_HW_ID:
517 return "HW_ID";
518 case SNS_STD_SENSOR_ATTRID_RIGID_BODY:
519 return "RIGID_BODY";
520 case SNS_STD_SENSOR_ATTRID_PLACEMENT:
521 return "PLACEMENT";
522 case SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR:
523 return "PHYSICAL_SENSOR";
524 case SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR_TESTS:
525 return "PHYSICAL_SENSOR_TESTS";
526 case SNS_STD_SENSOR_ATTRID_SELECTED_RESOLUTION:
527 return "SELECTED_RESOLUTION";
528 case SNS_STD_SENSOR_ATTRID_SELECTED_RANGE:
529 return "SELECTED_RANGE";
530 case SNS_STD_SENSOR_ATTRID_ADDITIONAL_LOW_LATENCY_RATES:
531 return "LOW_LATENCY_RATES";
532 case SNS_STD_SENSOR_ATTRID_PASSIVE_REQUEST:
533 return "PASSIVE_REQUEST";
534 default:
535 return "UNKNOWN ATTRIBUTE";
536 }
537 }
538
539 /**
540 * Decodes each attribute field and passes the value to the calling function.
541 * For repeated fields of float or integers, only store the maximum and
542 * minimum values for the calling function.
543 */
decodeSnsStdAttrValue(pb_istream_t * stream,const pb_field_t * field,void ** arg)544 bool decodeSnsStdAttrValue(pb_istream_t *stream, const pb_field_t *field,
545 void **arg) {
546 bool success = false;
547
548 struct DecodeData {
549 SeeBufArg strData;
550 SeeAttrArg subtypeAttrArg;
551 sns_std_attr_value_data value;
552 };
553 auto data = MakeUniqueZeroFill<DecodeData>();
554
555 if (data.isNull()) {
556 LOG_OOM();
557 } else {
558 data->value.str.funcs.decode = decodeStringField;
559 data->value.str.arg = &data->strData;
560 data->value.subtype.values.funcs.decode = decodeSnsStdAttrValue;
561 data->value.subtype.values.arg = &data->subtypeAttrArg;
562
563 success = pb_decode(stream, sns_std_attr_value_data_fields, &data->value);
564 if (!success) {
565 LOG_NANOPB_ERROR(stream);
566 } else {
567 auto *attrVal = static_cast<SeeAttrArg *>(*arg);
568 if (data->value.has_flt) {
569 // If this is a float (repeated) field, initialize the union as floats
570 // to store the maximum and minmum values of the repeated fields.
571 if (!attrVal->initialized) {
572 attrVal->initialized = true;
573 attrVal->fltMin = FLT_MAX;
574 attrVal->fltMax = FLT_MIN;
575 }
576 if (data->value.flt < attrVal->fltMin) {
577 attrVal->fltMin = data->value.flt;
578 }
579 if (data->value.flt > attrVal->fltMax) {
580 attrVal->fltMax = data->value.flt;
581 }
582 } else if (data->value.has_sint) {
583 attrVal->int64 = data->value.sint;
584 } else if (data->value.has_boolean) {
585 attrVal->boolVal = data->value.boolean;
586 } else if (data->strData.buf != nullptr) {
587 strlcpy(attrVal->strVal, static_cast<const char *>(data->strData.buf),
588 sizeof(attrVal->strVal));
589 } else if (!data->value.has_subtype) {
590 LOGW("Unknown attr type");
591 }
592 }
593 }
594 return success;
595 }
596
decodeSnsStrAttr(pb_istream_t * stream,const pb_field_t * field,void ** arg)597 bool decodeSnsStrAttr(pb_istream_t *stream, const pb_field_t *field,
598 void **arg) {
599 bool success = false;
600
601 struct Decodedata {
602 SeeAttrArg attrArg;
603 sns_std_attr attr;
604 };
605 auto data = MakeUniqueZeroFill<Decodedata>();
606
607 if (data.isNull()) {
608 LOG_OOM();
609 } else {
610 data->attr.value.values.funcs.decode = decodeSnsStdAttrValue;
611 data->attr.value.values.arg = &data->attrArg;
612
613 success = pb_decode(stream, sns_std_attr_fields, &data->attr);
614 if (!success) {
615 LOG_NANOPB_ERROR(stream);
616 } else {
617 auto *attrData = static_cast<SeeAttributes *>(*arg);
618 switch (data->attr.attr_id) {
619 case SNS_STD_SENSOR_ATTRID_NAME:
620 strlcpy(attrData->name, data->attrArg.strVal, sizeof(attrData->name));
621 break;
622 case SNS_STD_SENSOR_ATTRID_VENDOR:
623 strlcpy(attrData->vendor, data->attrArg.strVal,
624 sizeof(attrData->vendor));
625 break;
626 case SNS_STD_SENSOR_ATTRID_TYPE:
627 strlcpy(attrData->type, data->attrArg.strVal, sizeof(attrData->type));
628 break;
629 case SNS_STD_SENSOR_ATTRID_AVAILABLE:
630 if (!data->attrArg.boolVal) {
631 LOGW("%s: %d", getAttrNameFromAttrId(data->attr.attr_id),
632 data->attrArg.boolVal);
633 }
634 break;
635 case SNS_STD_SENSOR_ATTRID_RATES:
636 attrData->maxSampleRate = data->attrArg.fltMax;
637 break;
638 case SNS_STD_SENSOR_ATTRID_STREAM_TYPE:
639 attrData->streamType = data->attrArg.int64;
640 break;
641 case SNS_STD_SENSOR_ATTRID_HW_ID:
642 attrData->hwId = data->attrArg.int64;
643 break;
644 case SNS_STD_SENSOR_ATTRID_PASSIVE_REQUEST:
645 attrData->passiveRequest = data->attrArg.boolVal;
646 break;
647 default:
648 break;
649 }
650 }
651 }
652 return success;
653 }
654
decodeSnsStdAttrEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)655 bool decodeSnsStdAttrEvent(pb_istream_t *stream, const pb_field_t *field,
656 void **arg) {
657 bool success = false;
658
659 struct DecodeData {
660 SeeAttributes attr;
661 sns_std_attr_event event;
662 };
663 auto data = MakeUniqueZeroFill<DecodeData>();
664
665 if (data.isNull()) {
666 LOG_OOM();
667 } else {
668 data->event.attributes.funcs.decode = decodeSnsStrAttr;
669 data->event.attributes.arg = &data->attr;
670
671 success = pb_decode(stream, sns_std_attr_event_fields, &data->event);
672 if (!success) {
673 LOG_NANOPB_ERROR(stream);
674 } else {
675 auto *info = static_cast<SeeInfoArg *>(*arg);
676
677 // If syncData == nullptr, this indication is received outside of a sync
678 // call. If the decoded SUID doesn't match the one we are waiting for,
679 // this indication is from a previous getAttributes call and happens to
680 // arrive between a later findAttributesSync req/ind pair.
681 // Note that req/ind misalignment can still happen if getAttributesSync is
682 // called again with the same SUID.
683 if (info->sync->syncData == nullptr
684 || !suidsMatch(info->suid, info->sync->syncSuid)) {
685 LOGW("Received late SNS_STD_MSGID_SNS_STD_ATTR_EVENT indication");
686 } else {
687 info->sync->syncIndFound = true;
688 memcpy(info->sync->syncData, &data->attr, sizeof(data->attr));
689 }
690 }
691 }
692 return success;
693 }
694
695 /**
696 * Decode messages defined in sns_std.proto
697 */
decodeSnsStdProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)698 bool decodeSnsStdProtoEvent(pb_istream_t *stream, const pb_field_t *field,
699 void **arg) {
700 bool success = false;
701
702 auto *info = static_cast<SeeInfoArg *>(*arg);
703 switch (info->msgId) {
704 case SNS_STD_MSGID_SNS_STD_ATTR_EVENT:
705 success = decodeSnsStdAttrEvent(stream, field, arg);
706 break;
707
708 case SNS_STD_MSGID_SNS_STD_FLUSH_EVENT:
709 // An empty message.
710 success = true;
711 break;
712
713 case SNS_STD_MSGID_SNS_STD_ERROR_EVENT: {
714 sns_std_error_event event = {};
715 success = pb_decode(stream, sns_std_error_event_fields, &event);
716 if (!success) {
717 LOG_NANOPB_ERROR(stream);
718 } else {
719 LOGW("SNS_STD_MSGID_SNS_STD_ERROR_EVENT: %d", event.error);
720 }
721 break;
722 }
723
724 default:
725 LOGW("Unhandled sns_std.proto msg ID %" PRIu32, info->msgId);
726 }
727 return success;
728 }
729
730 // TODO: Support compensation matrix and scaling factor calibration
applyThreeAxisCalibration(chreSensorThreeAxisData::chreSensorThreeAxisSampleData * sample,const float * val,const SeeCalData * cal)731 void applyThreeAxisCalibration(
732 chreSensorThreeAxisData::chreSensorThreeAxisSampleData *sample,
733 const float *val, const SeeCalData *cal) {
734 float bias[3] = {};
735 if (cal != nullptr && cal->hasBias) {
736 memcpy(bias, cal->bias, sizeof(bias));
737 }
738 sample->x = val[0] - bias[0];
739 sample->y = val[1] - bias[1];
740 sample->z = val[2] - bias[2];
741 }
742
populateEventSample(SeeDataArg * data,const float * val)743 void populateEventSample(SeeDataArg *data, const float *val) {
744 size_t index = data->sampleIndex;
745 if (!data->event.isNull() && index < data->totalSamples) {
746 SensorSampleType sampleType = getSensorSampleTypeFromSensorType(
747 data->sensorType);
748
749 uint32_t *timestampDelta = nullptr;
750 switch (sampleType) {
751 case SensorSampleType::ThreeAxis: {
752 auto *event = reinterpret_cast<chreSensorThreeAxisData *>(
753 data->event.get());
754 applyThreeAxisCalibration(&event->readings[index], val, data->cal);
755 timestampDelta = &event->readings[index].timestampDelta;
756 break;
757 }
758
759 case SensorSampleType::Float: {
760 auto *event = reinterpret_cast<chreSensorFloatData *>(
761 data->event.get());
762 event->readings[index].value = val[0];
763 timestampDelta = &event->readings[index].timestampDelta;
764 break;
765 }
766
767 case SensorSampleType::Byte: {
768 auto *event = reinterpret_cast<chreSensorByteData *>(data->event.get());
769 event->readings[index].value = 0;
770 event->readings[index].isNear = (val[0] > 0.5f);
771 timestampDelta = &event->readings[index].timestampDelta;
772 break;
773 }
774
775 case SensorSampleType::Occurrence: {
776 auto *event = reinterpret_cast<chreSensorOccurrenceData *>(
777 data->event.get());
778 timestampDelta = &event->readings[index].timestampDelta;
779 break;
780 }
781
782 #ifdef CHREX_SENSOR_SUPPORT
783 case SensorSampleType::Vendor0: {
784 auto *event = reinterpret_cast<chrexSensorVendor0Data *>(
785 data->event.get());
786 memcpy(event->readings[index].values, val,
787 sizeof(event->readings[index].values));
788 timestampDelta = &event->readings[index].timestampDelta;
789 break;
790 }
791
792 case SensorSampleType::Vendor1: {
793 auto *event = reinterpret_cast<chrexSensorVendor1Data *>(
794 data->event.get());
795 memcpy(event->readings[index].values, val,
796 sizeof(event->readings[index].values));
797 timestampDelta = &event->readings[index].timestampDelta;
798 break;
799 }
800
801 case SensorSampleType::Vendor2: {
802 auto *event = reinterpret_cast<chrexSensorVendor2Data *>(
803 data->event.get());
804 event->readings[index].value = *val;
805 timestampDelta = &event->readings[index].timestampDelta;
806 break;
807 }
808 #endif // CHREX_SENSOR_SUPPORT
809
810 default:
811 LOGE("Invalid sample type %" PRIu8, static_cast<uint8_t>(sampleType));
812 }
813
814 if (data->sampleIndex == 0) {
815 auto *header = reinterpret_cast<chreSensorDataHeader *>(
816 data->event.get());
817 header->baseTimestamp = data->timeNs;
818 *timestampDelta = 0;
819 } else {
820 uint64_t delta = data->timeNs - data->prevTimeNs;
821 if (delta > UINT32_MAX) {
822 LOGE("Sensor %" PRIu8 " timestampDelta overflow: prev %" PRIu64
823 " curr %" PRIu64, static_cast<uint8_t>(data->sensorType),
824 data->prevTimeNs, data->timeNs);
825 delta = UINT32_MAX;
826 }
827 *timestampDelta = static_cast<uint32_t>(delta);
828 }
829 data->prevTimeNs = data->timeNs;
830 }
831 }
832
833 /**
834 * Decodes a float array and ensures that the data doesn't go out of bound.
835 */
decodeFloatData(pb_istream_t * stream,const pb_field_t * field,void ** arg)836 bool decodeFloatData(pb_istream_t *stream, const pb_field_t *field,
837 void **arg) {
838 auto *data = static_cast<SeeFloatArg *>(*arg);
839
840 float value;
841 float *fltPtr = &value;
842 if (data->index >= ARRAY_SIZE(data->val)) {
843 LOGE("Float array length exceeds %zu", ARRAY_SIZE(data->val));
844 } else {
845 // Decode to the provided array only if it doesn't go out of bound.
846 fltPtr = &(data->val[data->index]);
847 }
848 // Increment index whether it's gone out of bounds or not.
849 (data->index)++;
850
851 bool success = pb_decode_fixed32(stream, fltPtr);
852 if (!success) {
853 LOG_NANOPB_ERROR(stream);
854 }
855 return success;
856 }
857
decodeSnsStdSensorPhysicalConfigEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)858 bool decodeSnsStdSensorPhysicalConfigEvent(
859 pb_istream_t *stream, const pb_field_t *field, void **arg) {
860 SeeBufArg data = {};
861 sns_std_sensor_physical_config_event event = {
862 .operation_mode.funcs.decode = decodeStringField,
863 .operation_mode.arg = &data,
864 };
865
866 bool success = pb_decode(stream, sns_std_sensor_physical_config_event_fields,
867 &event);
868 if (!success) {
869 LOG_NANOPB_ERROR(stream);
870 } else {
871 auto statusData =
872 MakeUniqueZeroFill<SeeHelperCallbackInterface::SamplingStatusData>();
873 if (statusData.isNull()) {
874 LOG_OOM();
875 } else {
876 struct chreSensorSamplingStatus *status = &statusData->status;
877
878 if (event.has_sample_rate) {
879 statusData->intervalValid = true;
880 status->interval = static_cast<uint64_t>(
881 ceilf(Seconds(1).toRawNanoseconds() / event.sample_rate));
882 }
883
884 // If operation_mode is populated, decoded string length will be > 0.
885 if (data.bufLen > 0) {
886 statusData->enabledValid = true;
887 status->enabled =
888 (strncmp(static_cast<const char *>(data.buf), kOpModeOff,
889 std::min(data.bufLen, sizeof(kOpModeOff))) != 0);
890 }
891
892 if (event.has_sample_rate || data.bufLen > 0) {
893 auto *info = static_cast<SeeInfoArg *>(*arg);
894 statusData->sensorType = info->data->sensorType;
895 info->data->status = std::move(statusData);
896 }
897 }
898 }
899 return success;
900 }
901
decodeSnsStdSensorEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)902 bool decodeSnsStdSensorEvent(pb_istream_t *stream, const pb_field_t *field,
903 void **arg) {
904 SeeFloatArg sample = {};
905 sns_std_sensor_event event = {
906 .data.funcs.decode = decodeFloatData,
907 .data.arg = &sample,
908 };
909
910 bool success = pb_decode(stream, sns_std_sensor_event_fields, &event);
911 if (!success) {
912 LOG_NANOPB_ERROR(stream);
913 } else {
914 auto *info = static_cast<SeeInfoArg *>(*arg);
915 populateEventSample(info->data, sample.val);
916 }
917 return success;
918 }
919
920 /**
921 * Decode messages defined in sns_std_sensor.proto
922 */
decodeSnsStdSensorProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)923 bool decodeSnsStdSensorProtoEvent(pb_istream_t *stream, const pb_field_t *field,
924 void **arg) {
925 bool success = false;
926
927 auto *info = static_cast<SeeInfoArg *>(*arg);
928 switch (info->msgId) {
929 case SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_PHYSICAL_CONFIG_EVENT:
930 success = decodeSnsStdSensorPhysicalConfigEvent(stream, field, arg);
931 break;
932
933 case SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT:
934 success = decodeSnsStdSensorEvent(stream, field, arg);
935 break;
936
937 default:
938 LOGW("Unhandled sns_std_sensor.proto msg ID %" PRIu32, info->msgId);
939 }
940 return success;
941 }
942
decodeSnsCalEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)943 bool decodeSnsCalEvent(pb_istream_t *stream, const pb_field_t *field,
944 void **arg) {
945 SeeFloatArg offset = {};
946 SeeFloatArg scale = {};
947 SeeFloatArg matrix = {};
948 sns_cal_event event = {
949 .bias.funcs.decode = decodeFloatData,
950 .bias.arg = &offset,
951 .scale_factor.funcs.decode = decodeFloatData,
952 .scale_factor.arg = &scale,
953 .comp_matrix.funcs.decode = decodeFloatData,
954 .comp_matrix.arg = &matrix,
955 };
956
957 bool success = pb_decode(stream, sns_cal_event_fields, &event);
958 if (!success) {
959 LOG_NANOPB_ERROR(stream);
960 } else {
961 auto *info = static_cast<SeeInfoArg *>(*arg);
962 SeeCalInfo *calInfo = info->calInfo;
963 size_t calIndex = getCalIndexFromSuid(info->suid, calInfo);
964 if (calIndex >= kNumSeeCalSensors) {
965 LOGW("Cal sensor index out of bounds 0x%" PRIx64 " %" PRIx64,
966 info->suid.suid_high, info->suid.suid_low);
967 } else {
968 SeeCalData *cal = &calInfo[calIndex].cal;
969
970 cal->hasBias = (offset.index == 3);
971 if (cal->hasBias) {
972 memcpy(cal->bias, offset.val, sizeof(cal->bias));
973 }
974
975 cal->hasScale = (scale.index == 3);
976 if (cal->hasScale) {
977 memcpy(cal->scale, scale.val, sizeof(cal->scale));
978 }
979
980 cal->hasMatrix = (matrix.index == 9);
981 if (cal->hasScale) {
982 memcpy(cal->matrix, matrix.val, sizeof(cal->matrix));
983 }
984
985 cal->accuracy = static_cast<uint8_t>(event.status);
986 }
987 }
988 return success;
989 }
990
991 /**
992 * Decode messages defined in sns_cal.proto
993 */
decodeSnsCalProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)994 bool decodeSnsCalProtoEvent(pb_istream_t *stream, const pb_field_t *field,
995 void **arg) {
996 bool success = false;
997
998 auto *info = static_cast<SeeInfoArg *>(*arg);
999 switch (info->msgId) {
1000 case SNS_CAL_MSGID_SNS_CAL_EVENT:
1001 success = decodeSnsCalEvent(stream, field, arg);
1002 break;
1003
1004 default:
1005 LOGW("Unhandled sns_cal.proto msg ID %" PRIu32, info->msgId);
1006 }
1007 return success;
1008 }
1009
decodeSnsProximityEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)1010 bool decodeSnsProximityEvent(pb_istream_t *stream, const pb_field_t *field,
1011 void **arg) {
1012 sns_proximity_event event = {};
1013
1014 bool success = pb_decode(stream, sns_proximity_event_fields, &event);
1015 if (!success) {
1016 LOG_NANOPB_ERROR(stream);
1017 } else {
1018 float value = static_cast<float>(event.proximity_event_type);
1019 auto *info = static_cast<SeeInfoArg *>(*arg);
1020 populateEventSample(info->data, &value);
1021 }
1022 return success;
1023 }
1024
1025 /**
1026 * Decode messages defined in sns_proximity.proto
1027 */
decodeSnsProximityProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)1028 bool decodeSnsProximityProtoEvent(pb_istream_t *stream, const pb_field_t *field,
1029 void **arg) {
1030 bool success = false;
1031
1032 auto *info = static_cast<SeeInfoArg *>(*arg);
1033 switch (info->msgId) {
1034 case SNS_PROXIMITY_MSGID_SNS_PROXIMITY_EVENT:
1035 success = decodeSnsProximityEvent(stream, field, arg);
1036 break;
1037
1038 default:
1039 LOGW("Unhandled sns_proximity.proto msg ID %" PRIu32, info->msgId);
1040 }
1041 return success;
1042 }
1043
decodeSnsRemoteProcStateEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)1044 bool decodeSnsRemoteProcStateEvent(
1045 pb_istream_t *stream, const pb_field_t *field, void **arg) {
1046 sns_remote_proc_state_event event = sns_remote_proc_state_event_init_default;
1047 bool success = pb_decode(stream, sns_remote_proc_state_event_fields, &event);
1048 if (!success) {
1049 LOG_NANOPB_ERROR(stream);
1050 } else if (event.proc_type == SNS_STD_CLIENT_PROCESSOR_APSS) {
1051 auto *info = static_cast<SeeInfoArg *>(*arg);
1052 info->data->isHostWakeSuspendEvent = true;
1053 info->data->isHostAwake =
1054 (event.event_type == SNS_REMOTE_PROC_STATE_AWAKE);
1055 }
1056 return success;
1057 }
1058
1059 /**
1060 * Decode messages defined in sns_remote_proc_state.proto
1061 */
decodeSnsRemoteProcProtoEvent(pb_istream_t * stream,const pb_field_t * field,void ** arg)1062 bool decodeSnsRemoteProcProtoEvent(
1063 pb_istream_t *stream, const pb_field_t *field, void **arg) {
1064 bool success = false;
1065 auto *info = static_cast<SeeInfoArg *>(*arg);
1066 switch (info->msgId) {
1067 case SNS_REMOTE_PROC_STATE_MSGID_SNS_REMOTE_PROC_STATE_EVENT:
1068 success = decodeSnsRemoteProcStateEvent(stream, field, arg);
1069 break;
1070
1071 default:
1072 LOGW("Unhandled sns_remote_proc_state.proto msg ID %" PRIu32,
1073 info->msgId);
1074 }
1075 return success;
1076 }
1077
assignPayloadCallback(const SeeInfoArg * info,pb_callback_t * payload)1078 bool assignPayloadCallback(const SeeInfoArg *info, pb_callback_t *payload) {
1079 bool success = true;
1080
1081 payload->arg = const_cast<SeeInfoArg *>(info);
1082
1083 if (info->remoteProcSuid->has_value()
1084 && suidsMatch(info->suid, info->remoteProcSuid->value())) {
1085 payload->funcs.decode = decodeSnsRemoteProcProtoEvent;
1086 } else if (suidsMatch(info->suid, kSuidLookup)) {
1087 payload->funcs.decode = decodeSnsSuidProtoEvent;
1088 } else {
1089 // Assumed: "real" sensors SUIDs
1090 switch (info->msgId) {
1091 case SNS_STD_MSGID_SNS_STD_ATTR_EVENT:
1092 case SNS_STD_MSGID_SNS_STD_FLUSH_EVENT:
1093 case SNS_STD_MSGID_SNS_STD_ERROR_EVENT:
1094 payload->funcs.decode = decodeSnsStdProtoEvent;
1095 break;
1096
1097 case SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_PHYSICAL_CONFIG_EVENT:
1098 case SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT:
1099 payload->funcs.decode = decodeSnsStdSensorProtoEvent;
1100 break;
1101
1102 case SNS_CAL_MSGID_SNS_CAL_EVENT:
1103 payload->funcs.decode = decodeSnsCalProtoEvent;
1104 break;
1105
1106 case SNS_PROXIMITY_MSGID_SNS_PROXIMITY_EVENT:
1107 payload->funcs.decode = decodeSnsProximityProtoEvent;
1108 break;
1109
1110 default:
1111 success = false;
1112 LOGW("Unhandled msg ID %" PRIu32, info->msgId);
1113 }
1114 }
1115 return success;
1116 }
1117
1118 /**
1119 * Decodes only msg_id and timestamp defined in sns_client_event and converts
1120 * the timestamp to nanoseconds.
1121 */
decodeMsgIdAndTime(pb_istream_t * stream,uint32_t * msgId,uint64_t * timeNs)1122 bool decodeMsgIdAndTime(pb_istream_t *stream, uint32_t *msgId,
1123 uint64_t *timeNs) {
1124 sns_client_event_msg_sns_client_event event = {};
1125
1126 bool success = pb_decode(
1127 stream, sns_client_event_msg_sns_client_event_fields, &event);
1128 if (!success) {
1129 LOG_NANOPB_ERROR(stream);
1130 } else {
1131 *msgId = event.msg_id;
1132 *timeNs = getNanosecondsFromQTimerTicks(event.timestamp);
1133 }
1134 return success;
1135 }
1136
1137 /**
1138 * Decodes pb-encoded message
1139 */
decodeSnsClientEventMsg(pb_istream_t * stream,const pb_field_t * field,void ** arg)1140 bool decodeSnsClientEventMsg(pb_istream_t *stream, const pb_field_t *field,
1141 void **arg) {
1142 // Make a copy for data decoding.
1143 pb_istream_t streamCpy = *stream;
1144
1145 auto *info = static_cast<SeeInfoArg *>(*arg);
1146 bool success = decodeMsgIdAndTime(stream, &info->msgId, &info->data->timeNs);
1147
1148 if (success && !info->decodeMsgIdOnly) {
1149 sns_client_event_msg_sns_client_event event = {};
1150
1151 // Payload callback must be assigned if and only if we want to decode beyond
1152 // msg ID.
1153 success = assignPayloadCallback(info, &event.payload);
1154 if (!success) {
1155 LOGE("No pb callback assigned");
1156 } else {
1157 success = pb_decode(&streamCpy,
1158 sns_client_event_msg_sns_client_event_fields, &event);
1159 if (!success) {
1160 LOG_NANOPB_ERROR(&streamCpy);
1161 }
1162 }
1163 }
1164
1165 // Increment sample count only after sensor event decoding.
1166 if (success
1167 && (info->msgId == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT
1168 || info->msgId == SNS_PROXIMITY_MSGID_SNS_PROXIMITY_EVENT)) {
1169 info->data->sampleIndex++;
1170 }
1171 return success;
1172 }
1173
1174 /**
1175 * Obtain the SensorType from the list of registered SensorInfos.
1176 */
getSensorTypeFromSensorInfo(sns_client * client,const sns_std_suid & suid,const DynamicVector<SeeHelper::SensorInfo> & sensorInfos)1177 SensorType getSensorTypeFromSensorInfo(
1178 sns_client *client, const sns_std_suid& suid,
1179 const DynamicVector<SeeHelper::SensorInfo>& sensorInfos) {
1180 bool suidFound = false;
1181 SensorType otherType;
1182 for (const auto& sensorInfo : sensorInfos) {
1183 if (suidsMatch(sensorInfo.suid, suid)) {
1184 suidFound = true;
1185 if (sensorInfo.client == client) {
1186 return sensorInfo.sensorType;
1187 }
1188 otherType = sensorInfo.sensorType;
1189 }
1190 }
1191
1192 if (suidFound) {
1193 LOGE("Unmatched client: %p, SUID 0x%016" PRIx64 " %016" PRIx64,
1194 client, suid.suid_high, suid.suid_low);
1195 // TODO: remove after b/79993302 is resolved.
1196 for (const auto& sensorInfo : sensorInfos) {
1197 LOGE(" %p, 0x%016" PRIx64 " %016" PRIx64,
1198 sensorInfo.client,
1199 sensorInfo.suid.suid_high, sensorInfo.suid.suid_low);
1200 }
1201
1202 // Return SensorType in the other sns_client that matches the SUID as a
1203 // backup plan.
1204 return otherType;
1205 }
1206 return SensorType::Unknown;
1207 }
1208
1209 /**
1210 * Allocate event memory according to SensorType and the number of samples.
1211 */
allocateEvent(SensorType sensorType,size_t numSamples)1212 void *allocateEvent(SensorType sensorType, size_t numSamples) {
1213 SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
1214 size_t sampleSize = 0;
1215 switch (sampleType) {
1216 case SensorSampleType::ThreeAxis:
1217 sampleSize = sizeof(
1218 chreSensorThreeAxisData::chreSensorThreeAxisSampleData);
1219 break;
1220
1221 case SensorSampleType::Float:
1222 sampleSize = sizeof(
1223 chreSensorFloatData::chreSensorFloatSampleData);
1224 break;
1225
1226 case SensorSampleType::Byte:
1227 sampleSize = sizeof(
1228 chreSensorByteData::chreSensorByteSampleData);
1229 break;
1230
1231 case SensorSampleType::Occurrence:
1232 sampleSize = sizeof(
1233 chreSensorOccurrenceData::chreSensorOccurrenceSampleData);
1234 break;
1235
1236 #ifdef CHREX_SENSOR_SUPPORT
1237 case SensorSampleType::Vendor0:
1238 sampleSize = sizeof(chrexSensorVendor0SampleData);
1239 break;
1240
1241 case SensorSampleType::Vendor1:
1242 sampleSize = sizeof(chrexSensorVendor1SampleData);
1243 break;
1244
1245 case SensorSampleType::Vendor2:
1246 sampleSize = sizeof(chrexSensorVendor2SampleData);
1247 break;
1248 #endif // CHREX_SENSOR_SUPPORT
1249
1250 default:
1251 LOGE("Unhandled SensorSampleType for SensorType %" PRIu8,
1252 static_cast<uint8_t>(sensorType));
1253 }
1254
1255 size_t memorySize = (sampleType == SensorSampleType::Unknown)
1256 ? 0 : (sizeof(chreSensorDataHeader) + numSamples * sampleSize);
1257 void *event = (memorySize == 0) ? nullptr : memoryAlloc(memorySize);
1258
1259 if (event == nullptr && memorySize != 0) {
1260 LOG_OOM();
1261 }
1262 return event;
1263 }
1264
1265 // Allocates the sensor event memory and partially populates the header.
prepareSensorEvent(SeeInfoArg & info)1266 bool prepareSensorEvent(SeeInfoArg& info) {
1267 bool success = false;
1268
1269 UniquePtr<uint8_t> buf(static_cast<uint8 *>(
1270 allocateEvent(info.data->sensorType, info.data->sampleIndex)));
1271 info.data->event = std::move(buf);
1272
1273 if (!info.data->event.isNull()) {
1274 success = true;
1275
1276 info.data->prevTimeNs = 0;
1277
1278 auto *header = reinterpret_cast<chreSensorDataHeader *>(
1279 info.data->event.get());
1280 memset(header->reserved, 0, sizeof(header->reserved));
1281 header->sensorHandle = getSensorHandleFromSensorType(
1282 info.data->sensorType);
1283 header->readingCount = info.data->sampleIndex;
1284
1285 // Protect against out of bounds access in data decoding.
1286 info.data->totalSamples = info.data->sampleIndex;
1287
1288 // Reset sampleIndex only after memory has been allocated and header
1289 // populated.
1290 info.data->sampleIndex = 0;
1291 }
1292 return success;
1293 }
1294
1295 } // anonymous namespace
1296
1297 const SeeHelper::SnsClientApi SeeHelper::kDefaultApi = {
1298 .sns_client_init = sns_client_init,
1299 .sns_client_deinit = sns_client_deinit,
1300 .sns_client_send = sns_client_send,
1301 };
1302
~SeeHelper()1303 SeeHelper::~SeeHelper() {
1304 for (auto *client : mSeeClients) {
1305 int status = mSnsClientApi->sns_client_deinit(client);
1306 if (status != 0) {
1307 LOGE("Failed to release sensor client: %d", status);
1308 }
1309 }
1310 }
1311
handleSnsClientEventMsg(sns_client * client,const void * payload,size_t payloadLen)1312 void SeeHelper::handleSnsClientEventMsg(
1313 sns_client *client, const void *payload, size_t payloadLen) {
1314 CHRE_ASSERT(payload);
1315
1316 pb_istream_t stream = pb_istream_from_buffer(
1317 static_cast<const pb_byte_t *>(payload), payloadLen);
1318
1319 // Make a copy of the stream for sensor data decoding.
1320 pb_istream_t streamCpy = stream;
1321
1322 struct DecodeData {
1323 SeeSyncArg syncArg = {};
1324 SeeDataArg dataArg = {};
1325 SeeInfoArg info = {};
1326 sns_client_event_msg event = {};
1327 };
1328 auto data = MakeUnique<DecodeData>();
1329
1330 if (data.isNull()) {
1331 LOG_OOM();
1332 } else {
1333 // Only initialize fields that are not accessed in the main CHRE thread.
1334 data->info.client = client;
1335 data->info.sync = &data->syncArg;
1336 data->info.data = &data->dataArg;
1337 data->info.decodeMsgIdOnly = true;
1338 data->info.remoteProcSuid = &mRemoteProcSuid;
1339 data->info.calInfo = &mCalInfo[0];
1340 data->event.events.funcs.decode = decodeSnsClientEventMsg;
1341 data->event.events.arg = &data->info;
1342
1343 // Decode only SUID and MSG ID to help further decode.
1344 if (!pb_decode(&stream, sns_client_event_msg_fields, &data->event)) {
1345 LOG_NANOPB_ERROR(&stream);
1346 } else {
1347 data->info.suid = data->event.suid;
1348 data->info.decodeMsgIdOnly = false;
1349 data->info.data->cal = getCalDataFromSuid(data->info.suid);
1350 data->info.data->sensorType = getSensorTypeFromSensorInfo(
1351 data->info.client, data->info.suid, mSensorInfos);
1352
1353 mMutex.lock();
1354 bool synchronizedDecode = mWaitingOnInd;
1355 if (!synchronizedDecode) {
1356 // Early unlock, we're not going to use anything from the main thread.
1357 mMutex.unlock();
1358 } else {
1359 // Populate fields set by the main thread.
1360 data->info.sync->syncData = mSyncData;
1361 data->info.sync->syncDataType = mSyncDataType;
1362 data->info.sync->syncSuid = mSyncSuid;
1363 }
1364
1365 if (data->info.data->sampleIndex > 0) {
1366 if (data->info.data->sensorType == SensorType::Unknown) {
1367 LOGE("Unhandled sensor data SUID 0x%016" PRIx64 " %016" PRIx64,
1368 data->info.suid.suid_high, data->info.suid.suid_low);
1369 } else if (!prepareSensorEvent(data->info)) {
1370 LOGE("Failed to prepare sensor event");
1371 }
1372 }
1373
1374 if (!pb_decode(&streamCpy, sns_client_event_msg_fields, &data->event)) {
1375 LOG_NANOPB_ERROR(&streamCpy);
1376 } else if (synchronizedDecode && data->info.sync->syncIndFound) {
1377 mWaitingOnInd = false;
1378 mCond.notify_one();
1379 } else {
1380 if (data->info.data->isHostWakeSuspendEvent) {
1381 mCbIf->onHostWakeSuspendEvent(data->info.data->isHostAwake);
1382 }
1383 if (!data->info.data->event.isNull()) {
1384 mCbIf->onSensorDataEvent(
1385 data->info.data->sensorType, std::move(data->info.data->event));
1386 }
1387 if (!data->info.data->status.isNull()) {
1388 if (data->info.data->sensorType == SensorType::Unknown) {
1389 LOGE("Unhandled sensor status SUID 0x%016" PRIx64 " %016" PRIx64,
1390 data->info.suid.suid_high, data->info.suid.suid_low);
1391 } else {
1392 mCbIf->onSamplingStatusUpdate(std::move(data->info.data->status));
1393 }
1394 }
1395 }
1396
1397 if (synchronizedDecode) {
1398 mMutex.unlock();
1399 }
1400 }
1401 }
1402 }
1403
handleSeeResp(uint32_t txnId,sns_std_error error)1404 void SeeHelper::handleSeeResp(uint32_t txnId, sns_std_error error) {
1405 LockGuard<Mutex> lock(mMutex);
1406 if (mWaitingOnResp && txnId == mCurrentTxnId) {
1407 mRespError = error;
1408 mWaitingOnResp = false;
1409 mCond.notify_one();
1410 }
1411 }
1412
findSuidSync(const char * dataType,DynamicVector<sns_std_suid> * suids,uint8_t minNumSuids,uint32_t maxRetries,Milliseconds retryDelay)1413 bool SeeHelper::findSuidSync(const char *dataType,
1414 DynamicVector<sns_std_suid> *suids,
1415 uint8_t minNumSuids, uint32_t maxRetries,
1416 Milliseconds retryDelay) {
1417 CHRE_ASSERT(suids != nullptr);
1418 CHRE_ASSERT(minNumSuids > 0);
1419
1420 bool success = false;
1421 if (mSeeClients.empty()) {
1422 LOGE("Sensor client wasn't initialized");
1423 } else {
1424 UniquePtr<pb_byte_t> msg;
1425 size_t msgLen;
1426 if (encodeSnsSuidReq(dataType, &msg, &msgLen)) {
1427 // Sensor client service may come up before SEE sensors are enumerated. A
1428 // max dwell time is set and retries are performed as currently there's no
1429 // message indicating that SEE intialization is complete.
1430 uint32_t trialCount = 0;
1431 do {
1432 suids->clear();
1433 if (++trialCount > 1) {
1434 timer_sleep(retryDelay.getMilliseconds(), T_MSEC,
1435 true /* non_deferrable */);
1436 }
1437
1438 // Ignore failures from sendReq, we'll retry anyways (up to maxRetries)
1439 sendReq(sns_suid_sensor_init_default,
1440 suids, dataType,
1441 SNS_SUID_MSGID_SNS_SUID_REQ, msg.get(), msgLen,
1442 false /* batchValid */, 0 /* batchPeriodUs */,
1443 false /* passive */, true /* waitForIndication */);
1444 } while (suids->size() < minNumSuids && trialCount < maxRetries);
1445
1446 success = (suids->size() >= minNumSuids);
1447 if (!success) {
1448 mHaveTimedOutOnSuidLookup = true;
1449 }
1450 if (trialCount > 1) {
1451 LOGD("Waited %" PRIu32 " ms for %s (found: %d)",
1452 static_cast<uint32_t>(trialCount * retryDelay.getMilliseconds()),
1453 dataType, success);
1454 }
1455 }
1456 }
1457
1458 return success;
1459 }
1460
getAttributesSync(const sns_std_suid & suid,SeeAttributes * attr)1461 bool SeeHelper::getAttributesSync(const sns_std_suid& suid,
1462 SeeAttributes *attr) {
1463 CHRE_ASSERT(attr);
1464 bool success = false;
1465
1466 if (mSeeClients.empty()) {
1467 LOGE("Sensor client wasn't initialized");
1468 } else {
1469 UniquePtr<pb_byte_t> msg;
1470 size_t msgLen;
1471 success = encodeSnsStdAttrReq(&msg, &msgLen);
1472
1473 if (success) {
1474 success = sendReq(suid, attr, nullptr /* syncDataType */,
1475 SNS_STD_MSGID_SNS_STD_ATTR_REQ, msg.get(), msgLen,
1476 false /* batchValid */, 0 /* batchPeriodUs */,
1477 false /* passive */, true /* waitForIndication */);
1478 }
1479 }
1480 return success;
1481 }
1482
init(SeeHelperCallbackInterface * cbIf,Microseconds timeout)1483 bool SeeHelper::init(SeeHelperCallbackInterface *cbIf, Microseconds timeout) {
1484 CHRE_ASSERT(cbIf);
1485
1486 mCbIf = cbIf;
1487 sns_client *client;
1488
1489 // Initialize cal/remote_proc_state sensors before making sensor data request.
1490 return (waitForService(&client, timeout)
1491 && mSeeClients.push_back(client)
1492 && initCalSensors()
1493 && initRemoteProcSensor());
1494 }
1495
makeRequest(const SeeSensorRequest & request)1496 bool SeeHelper::makeRequest(const SeeSensorRequest& request) {
1497 bool success = false;
1498
1499 const SensorInfo *sensorInfo = getSensorInfo(request.sensorType);
1500 if (sensorInfo == nullptr) {
1501 LOGE("SensorType %" PRIu8 " hasn't been registered",
1502 static_cast<uint8_t>(request.sensorType));
1503 } else {
1504 uint32_t msgId;
1505 UniquePtr<pb_byte_t> msg;
1506 size_t msgLen = 0;
1507
1508 if (!request.enable) {
1509 // An empty message
1510 msgId = SNS_CLIENT_MSGID_SNS_CLIENT_DISABLE_REQ;
1511 success = true;
1512 } else if (sensorTypeIsContinuous(request.sensorType)) {
1513 msgId = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG;
1514 success = encodeSnsStdSensorConfig(request, &msg, &msgLen);
1515 } else {
1516 msgId = SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG;
1517 // No sample rate needed to configure on-change or one-shot sensors.
1518 success = true;
1519 }
1520
1521 if (success) {
1522 success = sendReq(sensorInfo->client, sensorInfo->suid,
1523 nullptr /* syncData */, nullptr /* syncDataType */,
1524 msgId, msg.get(), msgLen,
1525 true /* batchValid */, request.batchPeriodUs,
1526 request.passive, false /* waitForIndication */);
1527 }
1528 }
1529 return success;
1530 }
1531
getCalSuidFromSensorType(SensorType sensorType) const1532 const sns_std_suid& SeeHelper::getCalSuidFromSensorType(
1533 SensorType sensorType) const {
1534 static sns_std_suid suid = sns_suid_sensor_init_zero;
1535
1536 size_t calIndex = getCalIndexFromSensorType(sensorType);
1537 if (calIndex < kNumSeeCalSensors && mCalInfo[calIndex].suid.has_value()) {
1538 suid = mCalInfo[calIndex].suid.value();
1539 }
1540 return suid;
1541 }
1542
1543 /**
1544 * Sends a request to SEE and waits for the response.
1545 */
sendSeeReqSync(sns_client * client,sns_client_request_msg * req,Nanoseconds timeoutResp)1546 bool SeeHelper::sendSeeReqSync(
1547 sns_client *client, sns_client_request_msg *req, Nanoseconds timeoutResp) {
1548 CHRE_ASSERT(client);
1549 CHRE_ASSERT(req);
1550 bool success = false;
1551
1552 auto *cbData = memoryAlloc<SeeRespCbData>();
1553 if (cbData == nullptr) {
1554 LOG_OOM();
1555 } else {
1556 cbData->seeHelper = this;
1557
1558 {
1559 LockGuard<Mutex> lock(mMutex);
1560 CHRE_ASSERT(!mWaitingOnResp);
1561 mWaitingOnResp = true;
1562 cbData->txnId = ++mCurrentTxnId;
1563 }
1564
1565 int status = mSnsClientApi->sns_client_send(
1566 client, req, SeeHelper::seeRespCb, cbData);
1567 if (status != 0) {
1568 LOGE("Error sending SEE request %d", status);
1569 memoryFree(cbData);
1570 }
1571
1572 {
1573 LockGuard<Mutex> lock(mMutex);
1574
1575 if (status == 0) {
1576 bool waitSuccess = true;
1577
1578 while (mWaitingOnResp && waitSuccess) {
1579 waitSuccess = mCond.wait_for(mMutex, timeoutResp);
1580 }
1581
1582 if (!waitSuccess) {
1583 LOGE("SEE resp timed out after %" PRIu64 " ms",
1584 Milliseconds(timeoutResp).getMilliseconds());
1585 } else if (mRespError != SNS_STD_ERROR_NO_ERROR) {
1586 LOGE("SEE txn ID %" PRIu32 " failed with error %d",
1587 mCurrentTxnId, mRespError);
1588 } else {
1589 success = true;
1590 }
1591 }
1592 mWaitingOnResp = false;
1593 }
1594 }
1595 return success;
1596 }
1597
sendReq(sns_client * client,const sns_std_suid & suid,void * syncData,const char * syncDataType,uint32_t msgId,void * payload,size_t payloadLen,bool batchValid,uint32_t batchPeriodUs,bool passive,bool waitForIndication,Nanoseconds timeoutResp,Nanoseconds timeoutInd)1598 bool SeeHelper::sendReq(
1599 sns_client *client, const sns_std_suid& suid,
1600 void *syncData, const char *syncDataType,
1601 uint32_t msgId, void *payload, size_t payloadLen,
1602 bool batchValid, uint32_t batchPeriodUs, bool passive,
1603 bool waitForIndication, Nanoseconds timeoutResp, Nanoseconds timeoutInd) {
1604 UniquePtr<sns_client_request_msg> msg;
1605 SeeBufArg data;
1606 bool success = false;
1607
1608 if (prepSnsClientReq(suid, msgId, payload, payloadLen, batchValid,
1609 batchPeriodUs, passive, &msg, &data)) {
1610 if (waitForIndication) {
1611 prepareWaitForInd(suid, syncData, syncDataType);
1612 }
1613
1614 success = sendSeeReqSync(client, msg.get(), timeoutResp);
1615
1616 if (waitForIndication) {
1617 success = waitForInd(success, timeoutInd);
1618 }
1619 }
1620 return success;
1621 }
1622
prepareWaitForInd(const sns_std_suid & suid,void * syncData,const char * syncDataType)1623 void SeeHelper::prepareWaitForInd(const sns_std_suid& suid, void *syncData,
1624 const char *syncDataType) {
1625 LockGuard<Mutex> lock(mMutex);
1626 CHRE_ASSERT(!mWaitingOnInd);
1627 mWaitingOnInd = true;
1628
1629 // Specify members needed for a sync call.
1630 mSyncSuid = suid;
1631 mSyncData = syncData;
1632 mSyncDataType = syncDataType;
1633 }
1634
waitForInd(bool reqSent,Nanoseconds timeoutInd)1635 bool SeeHelper::waitForInd(bool reqSent, Nanoseconds timeoutInd) {
1636 bool success = reqSent;
1637
1638 LockGuard<Mutex> lock(mMutex);
1639 CHRE_ASSERT(!mWaitingOnResp);
1640 if (reqSent) {
1641 bool waitSuccess = true;
1642
1643 while (mWaitingOnInd && waitSuccess) {
1644 waitSuccess = mCond.wait_for(mMutex, timeoutInd);
1645 }
1646
1647 if (!waitSuccess) {
1648 LOGE("SEE indication timed out after %" PRIu64 " ms",
1649 Milliseconds(timeoutInd).getMilliseconds());
1650 success = false;
1651 }
1652 }
1653 mWaitingOnInd = false;
1654
1655 // Reset members needed for a sync call.
1656 mSyncSuid = sns_suid_sensor_init_zero;
1657 mSyncData = nullptr;
1658 mSyncDataType = nullptr;
1659
1660 return success;
1661 }
1662
seeIndCb(sns_client * client,void * msg,uint32_t msgLen,void * cbData)1663 void SeeHelper::seeIndCb(
1664 sns_client *client, void *msg, uint32_t msgLen, void *cbData) {
1665 auto *obj = static_cast<SeeHelper *>(cbData);
1666 obj->handleSnsClientEventMsg(client, msg, msgLen);
1667 }
1668
seeRespCb(sns_client * client,sns_std_error error,void * cbData)1669 void SeeHelper::seeRespCb(sns_client *client, sns_std_error error,
1670 void *cbData) {
1671 auto *respCbData = static_cast<SeeRespCbData *>(cbData);
1672 respCbData->seeHelper->handleSeeResp(respCbData->txnId, error);
1673 memoryFree(cbData);
1674 }
1675
registerSensor(SensorType sensorType,const sns_std_suid & suid,bool * prevRegistered)1676 bool SeeHelper::registerSensor(
1677 SensorType sensorType, const sns_std_suid& suid, bool *prevRegistered) {
1678 CHRE_ASSERT(sensorType != SensorType::Unknown);
1679 CHRE_ASSERT(prevRegistered != nullptr);
1680 bool success = false;
1681
1682 // Check whether the SUID/SensorType pair has been previously registered.
1683 // Also count how many other SensorTypes the SUID has been registered with.
1684 *prevRegistered = false;
1685 size_t suidRegCount = 0;
1686 for (const auto& sensorInfo : mSensorInfos) {
1687 if (suidsMatch(suid, sensorInfo.suid)) {
1688 suidRegCount++;
1689 if (sensorInfo.sensorType == sensorType) {
1690 *prevRegistered = true;
1691 }
1692 }
1693 }
1694
1695 // Initialize another SEE client if the SUID has been previously
1696 // registered with more SensorTypes than the number of SEE clients can
1697 // disambiguate.
1698 bool clientAvailable = true;
1699 if (mSeeClients.size() <= suidRegCount) {
1700 sns_client *client;
1701 clientAvailable = waitForService(&client);
1702 if (clientAvailable) {
1703 clientAvailable = mSeeClients.push_back(client);
1704 }
1705 }
1706
1707 // Add a new entry only if this SUID/SensorType pair hasn't been registered.
1708 if (!*prevRegistered && clientAvailable) {
1709 SensorInfo sensorInfo = {
1710 .suid = suid,
1711 .sensorType = sensorType,
1712 .client = mSeeClients[suidRegCount],
1713 };
1714 success = mSensorInfos.push_back(sensorInfo);
1715 }
1716 return success;
1717 }
1718
sensorIsRegistered(SensorType sensorType) const1719 bool SeeHelper::sensorIsRegistered(SensorType sensorType) const {
1720 return (getSensorInfo(sensorType) != nullptr);
1721 }
1722
waitForService(sns_client ** client,Microseconds timeout)1723 bool SeeHelper::waitForService(sns_client **client,
1724 Microseconds timeout) {
1725 CHRE_ASSERT(client);
1726
1727 // TODO: add error_cb and error_cb_data.
1728 int status = mSnsClientApi->sns_client_init(
1729 client, timeout.getMilliseconds(),
1730 SeeHelper::seeIndCb, this /* ind_cb_data */,
1731 nullptr /* error_cb */, nullptr /* error_cb_data */);
1732
1733 bool success = (status == 0);
1734 if (!success) {
1735 LOGE("Failed to initialize the sensor client: %d", status);
1736 }
1737 return success;
1738 }
1739
initCalSensors()1740 bool SeeHelper::initCalSensors() {
1741 bool success = true;
1742
1743 // Zero out mCalInfo to avoid accidental suid and data match.
1744 memset(mCalInfo, 0, sizeof(mCalInfo));
1745
1746 const char *kCalTypes[] = {
1747 "accel_cal",
1748 "gyro_cal",
1749 "mag_cal",
1750 };
1751
1752 // Find the cal sensor's SUID, assign it to mCalInfo, and make cal sensor data
1753 // request.
1754 DynamicVector<sns_std_suid> suids;
1755 for (size_t i = 0; i < ARRAY_SIZE(kCalTypes); i++) {
1756 const char *calType = kCalTypes[i];
1757 if (!findSuidSync(calType, &suids)) {
1758 success = false;
1759 LOGE("Failed to find sensor '%s'", calType);
1760 } else {
1761 size_t index = getCalIndexFromDataType(calType);
1762 if (index >= kNumSeeCalSensors) {
1763 success = false;
1764 LOGE("Cal sensor '%s' index out of bounds", calType);
1765 } else {
1766 mCalInfo[index].suid = suids[0];
1767
1768 if (!sendReq(suids[0], nullptr /* syncData */,
1769 nullptr /* syncDataType */,
1770 SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG,
1771 nullptr /* msg */, 0 /* msgLen */,
1772 false /* batchValid */, 0 /* batchPeriodUs */,
1773 false /* passive */, false /* waitForIndication */)) {
1774 success = false;
1775 LOGE("Failed to request '%s' data", calType);
1776 }
1777 }
1778 }
1779 }
1780
1781 return success;
1782 }
1783
initRemoteProcSensor()1784 bool SeeHelper::initRemoteProcSensor() {
1785 bool success = false;
1786
1787 const char *kRemoteProcType = "remote_proc_state";
1788 DynamicVector<sns_std_suid> suids;
1789 if (!findSuidSync(kRemoteProcType, &suids)) {
1790 LOGE("Failed to find sensor '%s'", kRemoteProcType);
1791 } else {
1792 mRemoteProcSuid = suids[0];
1793
1794 uint32_t msgId = SNS_REMOTE_PROC_STATE_MSGID_SNS_REMOTE_PROC_STATE_CONFIG;
1795 constexpr size_t kBufferSize = sns_remote_proc_state_config_size;
1796 pb_byte_t msgBuffer[kBufferSize];
1797 size_t msgLen;
1798 if (encodeSnsRemoteProcSensorConfig(msgBuffer, kBufferSize, &msgLen,
1799 SNS_STD_CLIENT_PROCESSOR_APSS)) {
1800 success = sendReq(mRemoteProcSuid.value(),
1801 nullptr /* syncData */, nullptr /* syncDataType */,
1802 msgId, msgBuffer, msgLen,
1803 false /* batchValid */, 0 /* batchPeriodUs */,
1804 false /* passive */, false /* waitForIndication */);
1805 if (!success) {
1806 LOGE("Failed to request '%s' config", kRemoteProcType);
1807 }
1808 }
1809 }
1810
1811 return success;
1812 }
1813
getCalDataFromSuid(const sns_std_suid & suid)1814 SeeCalData *SeeHelper::getCalDataFromSuid(const sns_std_suid& suid) {
1815 size_t calIndex = getCalIndexFromSuid(suid, mCalInfo);
1816 return (calIndex < kNumSeeCalSensors) ? &mCalInfo[calIndex].cal : nullptr;
1817 }
1818
getSensorInfo(SensorType sensorType) const1819 const SeeHelper::SensorInfo *SeeHelper::getSensorInfo(
1820 SensorType sensorType) const {
1821 for (const auto& sensorInfo : mSensorInfos) {
1822 if (sensorInfo.sensorType == sensorType) {
1823 return &sensorInfo;
1824 }
1825 }
1826 return nullptr;
1827 }
1828
1829 } // namespace chre
1830