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/platform_sensor.h"
18
19 #include "sns_std_sensor.pb.h"
20 #include "stringl.h"
21
22 #include <cmath>
23
24 #include "chre_api/chre/sensor.h"
25 #include "chre/core/event_loop_manager.h"
26 #include "chre/core/sensor.h"
27 #include "chre/platform/assert.h"
28 #include "chre/platform/fatal_error.h"
29 #include "chre/platform/log.h"
30 #include "chre/platform/shared/platform_sensor_util.h"
31 #include "chre/platform/slpi/see/see_client.h"
32 #include "chre/platform/slpi/see/see_helper.h"
33 #include "chre/platform/system_time.h"
34
35 #ifdef CHREX_SENSOR_SUPPORT
36 #include "chre/extensions/platform/slpi/see/vendor_data_types.h"
37 #endif // CHREX_SENSOR_SUPPORT
38
39 #ifndef CHRE_SEE_NUM_TEMP_SENSORS
40 // There are usually more than one 'sensor_temperature' sensors in SEE.
41 // Define this in the variant-specific makefile to avoid missing sensors in
42 // sensor discovery.
43 #error "CHRE_SEE_NUM_TEMP_SENSORS is not defined"
44 #endif
45
46 namespace chre {
47 namespace {
48
49 //! A class that implements SeeHelperCallbackInterface.
50 class SeeHelperCallback : public SeeHelperCallbackInterface {
51 void onSamplingStatusUpdate(
52 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status)
53 override;
54
55 void onSensorDataEvent(
56 SensorType sensorType, UniquePtr<uint8_t>&& eventData) override;
57
58 void onHostWakeSuspendEvent(bool awake) override;
59 };
60
61 //! A struct to facilitate sensor discovery
62 struct SuidAttr {
63 sns_std_suid suid;
64 SeeAttributes attr;
65 };
66
67 //! The list of SEE platform sensor data types that CHRE intends to support.
68 //! The standardized strings are defined in sns_xxx.proto.
69 const char *kSeeDataTypes[] = {
70 "accel",
71 "gyro",
72 "mag",
73 "pressure",
74 "ambient_light",
75 "proximity",
76 "motion_detect",
77 "stationary_detect",
78 };
79
80 /**
81 * Obtains the sensor type given the specified data type and whether the sensor
82 * is runtime-calibrated or not.
83 */
getSensorTypeFromDataType(const char * dataType,bool calibrated)84 SensorType getSensorTypeFromDataType(const char *dataType, bool calibrated) {
85 SensorType sensorType;
86 if (strcmp(dataType, "accel") == 0) {
87 if (calibrated) {
88 sensorType = SensorType::Accelerometer;
89 } else {
90 sensorType = SensorType::UncalibratedAccelerometer;
91 }
92 } else if (strcmp(dataType, "gyro") == 0) {
93 if (calibrated) {
94 sensorType = SensorType::Gyroscope;
95 } else {
96 sensorType = SensorType::UncalibratedGyroscope;
97 }
98 } else if (strcmp(dataType, "mag") == 0) {
99 if (calibrated) {
100 sensorType = SensorType::GeomagneticField;
101 } else {
102 sensorType = SensorType::UncalibratedGeomagneticField;
103 }
104 } else if (strcmp(dataType, "pressure") == 0) {
105 sensorType = SensorType::Pressure;
106 } else if (strcmp(dataType, "ambient_light") == 0) {
107 sensorType = SensorType::Light;
108 } else if (strcmp(dataType, "proximity") == 0) {
109 sensorType = SensorType::Proximity;
110 } else if (strcmp(dataType, "motion_detect") == 0) {
111 sensorType = SensorType::InstantMotion;
112 } else if (strcmp(dataType, "stationary_detect") == 0) {
113 sensorType = SensorType::StationaryDetect;
114 #ifdef CHREX_SENSOR_SUPPORT
115 } else if (strcmp(dataType, kVendorDataTypes[0]) == 0) {
116 sensorType = SensorType::VendorType0;
117 #endif // CHREX_SENSOR_SUPPORT
118 } else {
119 sensorType = SensorType::Unknown;
120 }
121 return sensorType;
122 }
123
seeSensorDataEventFree(uint16_t eventType,void * eventData)124 void seeSensorDataEventFree(uint16_t eventType, void *eventData) {
125 memoryFree(eventData);
126
127 // Remove all requests if it's a one-shot sensor and only after data has been
128 // delivered to all clients.
129 SensorType sensorType = getSensorTypeForSampleEventType(eventType);
130 if (sensorTypeIsOneShot(sensorType)) {
131 EventLoopManagerSingleton::get()->getSensorRequestManager()
132 .removeAllRequests(sensorType);
133 }
134 }
135
136 /**
137 * Posts a CHRE_EVENT_SENSOR_SAMPLING_CHANGE event to the specified Nanoapp.
138 *
139 * @param instaceId The instance ID of the nanoapp with an open request.
140 * @param sensorHandle The handle of the sensor.
141 * @param status A reference of the sampling status to be posted.
142 */
postSamplingStatusEvent(uint32_t instanceId,uint32_t sensorHandle,const struct chreSensorSamplingStatus & status)143 void postSamplingStatusEvent(uint32_t instanceId, uint32_t sensorHandle,
144 const struct chreSensorSamplingStatus& status) {
145 auto *event = memoryAlloc<struct chreSensorSamplingStatusEvent>();
146 if (event == nullptr) {
147 LOG_OOM();
148 } else {
149 event->sensorHandle = sensorHandle;
150 event->status = status;
151
152 EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
153 CHRE_EVENT_SENSOR_SAMPLING_CHANGE, event, freeEventDataCallback,
154 kSystemInstanceId, instanceId);
155 }
156 }
157
158 /**
159 * Updates the sampling status.
160 */
updateSamplingStatus(const SeeHelperCallbackInterface::SamplingStatusData & update)161 void updateSamplingStatus(
162 const SeeHelperCallbackInterface::SamplingStatusData& update) {
163 Sensor *sensor = EventLoopManagerSingleton::get()->getSensorRequestManager()
164 .getSensor(update.sensorType);
165 struct chreSensorSamplingStatus prevStatus;
166
167 if (sensor != nullptr && !sensorTypeIsOneShot(update.sensorType)
168 && sensor->getSamplingStatus(&prevStatus)) {
169 struct chreSensorSamplingStatus newStatus = prevStatus;
170
171 if (update.enabledValid) {
172 newStatus.enabled = update.status.enabled;
173 }
174 if (update.intervalValid) {
175 newStatus.interval = update.status.interval;
176 }
177 if (update.latencyValid) {
178 newStatus.latency = update.status.latency;
179 }
180
181 if (newStatus.enabled != prevStatus.enabled
182 || newStatus.interval != prevStatus.interval
183 || newStatus.latency != prevStatus.latency) {
184 sensor->setSamplingStatus(newStatus);
185
186 // Only post to Nanoapps with an open request.
187 uint32_t sensorHandle = getSensorHandleFromSensorType(update.sensorType);
188 const DynamicVector<SensorRequest>& requests =
189 EventLoopManagerSingleton::get()->getSensorRequestManager()
190 .getRequests(update.sensorType);
191 for (const auto& req : requests) {
192 if (req.getNanoapp() != nullptr) {
193 postSamplingStatusEvent(req.getNanoapp()->getInstanceId(),
194 sensorHandle, newStatus);
195 }
196 }
197 }
198 }
199 }
200
onSamplingStatusUpdate(UniquePtr<SeeHelperCallbackInterface::SamplingStatusData> && status)201 void SeeHelperCallback::onSamplingStatusUpdate(
202 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status) {
203 auto callback = [](uint16_t /* type */, void *data) {
204 auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>(
205 static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(data));
206 updateSamplingStatus(*cbData);
207 };
208
209 // Schedule a deferred callback to handle sensor status change in the main
210 // thread.
211 EventLoopManagerSingleton::get()->deferCallback(
212 SystemCallbackType::SensorStatusUpdate, status.release(), callback);
213 }
214
onSensorDataEvent(SensorType sensorType,UniquePtr<uint8_t> && eventData)215 void SeeHelperCallback::onSensorDataEvent(
216 SensorType sensorType, UniquePtr<uint8_t>&& eventData) {
217 // Schedule a deferred callback to update on-change sensor's last event in
218 // the main thread.
219 if (sensorTypeIsOnChange(sensorType)) {
220 updateLastEvent(sensorType, eventData.get());
221 }
222
223 uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
224 EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
225 eventType, eventData.get(), seeSensorDataEventFree);
226 eventData.release();
227 }
228
onHostWakeSuspendEvent(bool awake)229 void SeeHelperCallback::onHostWakeSuspendEvent(bool awake) {
230 if (EventLoopManagerSingleton::isInitialized()) {
231 EventLoopManagerSingleton::get()->getEventLoop()
232 .getPowerControlManager().onHostWakeSuspendEvent(awake);
233 }
234 }
235
236 /**
237 * Allocates memory and specifies the memory size for an on-change sensor to
238 * store its last data event.
239 *
240 * @param sensorType The sensorType of this sensor.
241 * @param eventSize A non-null pointer to indicate the memory size allocated.
242 * @return Pointer to the memory allocated.
243 */
allocateLastEvent(SensorType sensorType,size_t * eventSize)244 ChreSensorData *allocateLastEvent(SensorType sensorType, size_t *eventSize) {
245 CHRE_ASSERT(eventSize);
246
247 *eventSize = 0;
248 ChreSensorData *event = nullptr;
249 if (sensorTypeIsOnChange(sensorType)) {
250 SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType);
251 switch (sampleType) {
252 case SensorSampleType::ThreeAxis:
253 *eventSize = sizeof(chreSensorThreeAxisData);
254 break;
255 case SensorSampleType::Float:
256 *eventSize = sizeof(chreSensorFloatData);
257 break;
258 case SensorSampleType::Byte:
259 *eventSize = sizeof(chreSensorByteData);
260 break;
261 case SensorSampleType::Occurrence:
262 *eventSize = sizeof(chreSensorOccurrenceData);
263 break;
264 default:
265 CHRE_ASSERT_LOG(false, "Unhandled sample type");
266 break;
267 }
268
269 event = static_cast<ChreSensorData *>(memoryAlloc(*eventSize));
270 if (event == nullptr) {
271 *eventSize = 0;
272 FATAL_ERROR("Failed to allocate last event memory for SensorType %" PRIu8,
273 static_cast<uint8_t>(sensorType));
274 }
275 }
276 return event;
277 }
278
279 /**
280 * Constructs and initializes a sensor, and adds it to the sensor list.
281 *
282 * @param suid The SUID of the sensor as provided by SEE.
283 * @param sensorType The sensor type of the sensor.
284 * @param calibrated Whether the sensor is runtime-calibrated or not.
285 * @param attr A reference to SeeAttrbutes.
286 * @param sensor The sensor list.
287 */
addSensor(SensorType sensorType,const sns_std_suid & suid,const SeeAttributes & attr,DynamicVector<Sensor> * sensors)288 void addSensor(SensorType sensorType, const sns_std_suid& suid,
289 const SeeAttributes& attr, DynamicVector<Sensor> *sensors) {
290 // Concatenate vendor and name with a space in between.
291 char sensorName[kSensorNameMaxLen];
292 strlcpy(sensorName, attr.vendor, sizeof(sensorName));
293 strlcat(sensorName, " ", sizeof(sensorName));
294 strlcat(sensorName, attr.name, sizeof(sensorName));
295
296 // Override one-shot sensor's minInterval to default
297 uint64_t minInterval = sensorTypeIsOneShot(sensorType) ?
298 CHRE_SENSOR_INTERVAL_DEFAULT : static_cast<uint64_t>(
299 ceilf(Seconds(1).toRawNanoseconds() / attr.maxSampleRate));
300
301 // Allocates memory for on-change sensor's last event.
302 size_t lastEventSize;
303 ChreSensorData *lastEvent = allocateLastEvent(sensorType, &lastEventSize);
304
305 // Constructs and initializes PlatformSensorBase.
306 Sensor sensor;
307 sensor.initBase(sensorType, minInterval, sensorName, lastEvent,
308 lastEventSize, attr.passiveRequest);
309
310 if (!sensors->push_back(std::move(sensor))) {
311 FATAL_ERROR("Failed to allocate new sensor: out of memory");
312 }
313
314 bool prevRegistered;
315 bool registered = getSeeHelper()->registerSensor(
316 sensorType, suid, &prevRegistered);
317 if (!registered && prevRegistered) {
318 LOGW("SUID has been previously registered");
319 } else if (!registered) {
320 FATAL_ERROR("Failed to register SUID/SensorType mapping.");
321 }
322 }
323
324 /**
325 * Compare SEE reported stream type attribute to the expected one. Some SEE
326 * sensors may support more than one stream type.
327 */
isStreamTypeCorrect(SensorType sensorType,uint8_t streamType)328 bool isStreamTypeCorrect(SensorType sensorType, uint8_t streamType) {
329 bool success = true;
330 if ((sensorTypeIsContinuous(sensorType)
331 && streamType != SNS_STD_SENSOR_STREAM_TYPE_STREAMING)
332 || (sensorTypeIsOnChange(sensorType)
333 && streamType != SNS_STD_SENSOR_STREAM_TYPE_ON_CHANGE)
334 || (sensorTypeIsOneShot(sensorType)
335 && streamType != SNS_STD_SENSOR_STREAM_TYPE_SINGLE_OUTPUT)) {
336 success = false;
337 LOGW("Inconsistent sensor type %" PRIu8 " and stream type %" PRIu8,
338 static_cast<uint8_t>(sensorType), streamType);
339 }
340 return success;
341 }
342
343 /**
344 * Obtains the list of SUIDs and their attributes that support the specified
345 * data type.
346 */
getSuidAndAttrs(const char * dataType,DynamicVector<SuidAttr> * suidAttrs,uint8_t minNumSuids)347 bool getSuidAndAttrs(const char *dataType, DynamicVector<SuidAttr> *suidAttrs,
348 uint8_t minNumSuids) {
349 DynamicVector<sns_std_suid> suids;
350 bool success = getSeeHelper()->findSuidSync(dataType, &suids, minNumSuids);
351 if (!success) {
352 LOGE("Failed to find sensor '%s'", dataType);
353 } else {
354 LOGD("Num of SUIDs found for '%s': %zu", dataType, suids.size());
355
356 for (const auto& suid : suids) {
357 SeeAttributes attr;
358 if (!getSeeHelper()->getAttributesSync(suid, &attr)) {
359 success = false;
360 LOGE("Failed to get attributes of SUID 0x%" PRIx64 " %" PRIx64,
361 suid.suid_high, suid.suid_low);
362 } else {
363 LOGI("%s %s, hw id %" PRId64 ", max ODR %f Hz, stream type %" PRIu8
364 " passive %d",
365 attr.vendor, attr.name, attr.hwId, attr.maxSampleRate,
366 attr.streamType, attr.passiveRequest);
367 SuidAttr sensor = {
368 .suid = suid,
369 .attr = attr,
370 };
371 if (!suidAttrs->push_back(sensor)) {
372 success = false;
373 LOG_OOM();
374 }
375 }
376 }
377 }
378 return success;
379 }
380
381 // Check whether two sensors with the specified attrtibutes belong to the same
382 // sensor hardware module.
sensorHwMatch(const SeeAttributes & attr0,const SeeAttributes & attr1)383 bool sensorHwMatch(const SeeAttributes& attr0, const SeeAttributes& attr1) {
384 // When HW ID is absent, it's default to 0 and won't be a factor.
385 return ((strncmp(attr0.vendor, attr1.vendor, kSeeAttrStrValLen) == 0)
386 && (strncmp(attr0.name, attr1.name, kSeeAttrStrValLen) == 0)
387 && (attr0.hwId == attr1.hwId));
388 }
389
390 } // anonymous namespace
391
~PlatformSensor()392 PlatformSensor::~PlatformSensor() {
393 if (mLastEvent != nullptr) {
394 LOGD("Releasing lastEvent: sensor %s, size %zu",
395 getSensorTypeName(getSensorType()), mLastEventSize);
396 memoryFree(mLastEvent);
397 }
398 }
399
init()400 void PlatformSensor::init() {
401 SeeHelperSingleton::init();
402
403 static SeeHelperCallback seeHelperCallback;
404 if (!getSeeHelper()->init(&seeHelperCallback)) {
405 FATAL_ERROR("Failed to initialize SEE helper");
406 }
407 }
408
deinit()409 void PlatformSensor::deinit() {
410 SeeHelperSingleton::deinit();
411 }
412
getSensors(DynamicVector<Sensor> * sensors)413 bool PlatformSensor::getSensors(DynamicVector<Sensor> *sensors) {
414 CHRE_ASSERT(sensors);
415
416 DynamicVector<SuidAttr> tempSensors;
417 if (!getSuidAndAttrs("sensor_temperature", &tempSensors,
418 CHRE_SEE_NUM_TEMP_SENSORS)) {
419 FATAL_ERROR("Failed to get temperature sensor UID and attributes");
420 }
421
422 #ifndef CHREX_SENSOR_SUPPORT
423 const char *kVendorDataTypes[] = {};
424 #endif // CHREX_SENSOR_SUPPORT
425 constexpr size_t kNumSeeTypes = ARRAY_SIZE(kSeeDataTypes);
426 constexpr size_t kNumVendorTypes = ARRAY_SIZE(kVendorDataTypes);
427 for (size_t i = 0; i < kNumSeeTypes + kNumVendorTypes; i++) {
428 const char *dataType = (i < kNumSeeTypes)
429 ? kSeeDataTypes[i] : kVendorDataTypes[i - kNumSeeTypes];
430
431 SensorType sensorType = getSensorTypeFromDataType(
432 dataType, false /* calibrated */);
433 if (sensorType == SensorType::Unknown) {
434 LOGE("Unknown sensor type found for '%s'", dataType);
435 continue;
436 }
437
438 DynamicVector<SuidAttr> primarySensors;
439 if (!getSuidAndAttrs(dataType, &primarySensors, 1 /* minNumSuids */)) {
440 FATAL_ERROR("Failed to get primary sensor UID and attributes");
441 } else {
442 for (const auto& primarySensor : primarySensors) {
443 sns_std_suid suid = primarySensor.suid;
444 SeeAttributes attr = primarySensor.attr;
445
446 // Some sensors support both continuous and on-change streams.
447 // If there are more than one SUIDs that support the data type,
448 // choose the first one that has the expected stream type.
449 if (isStreamTypeCorrect(sensorType, attr.streamType)) {
450 addSensor(sensorType, suid, attr, sensors);
451
452 // Check if this sensor has a runtime-calibrated version.
453 SensorType calibratedType = getSensorTypeFromDataType(
454 dataType, true /* calibrated */);
455 if (calibratedType != sensorType) {
456 addSensor(calibratedType, suid, attr, sensors);
457 }
458
459 // Check if this sensor has a secondary temperature sensor.
460 SensorType temperatureType = getTempSensorType(sensorType);
461 if (temperatureType != SensorType::Unknown) {
462 bool tempFound = false;
463 for (const auto& tempSensor : tempSensors) {
464 sns_std_suid tempSuid = tempSensor.suid;
465 SeeAttributes tempAttr = tempSensor.attr;
466
467 if (sensorHwMatch(attr, tempAttr)) {
468 LOGD("Found matching temperature sensor type");
469 tempFound = true;
470 addSensor(temperatureType, tempSuid, tempAttr, sensors);
471 break;
472 }
473 }
474 if (!tempFound) {
475 LOGW("Temperature sensor type %" PRIu8 " not found!",
476 static_cast<uint8_t>(temperatureType));
477 }
478 }
479 break;
480 }
481 }
482 }
483 }
484 return true;
485 }
486
applyRequest(const SensorRequest & request)487 bool PlatformSensor::applyRequest(const SensorRequest& request) {
488 SeeSensorRequest req = {
489 .sensorType = getSensorType(),
490 .enable = (request.getMode() != SensorMode::Off),
491 .passive = sensorModeIsPassive(request.getMode()),
492 .samplingRateHz = static_cast<float>(
493 kOneSecondInNanoseconds / request.getInterval().toRawNanoseconds()),
494 // Override batch period to 0 for non-continuous sensors to ensure one
495 // sample per batch.
496 .batchPeriodUs = !sensorTypeIsContinuous(mSensorType) ? 0
497 : static_cast<uint32_t>(request.getLatency().toRawNanoseconds()
498 / kOneMicrosecondInNanoseconds),
499 };
500
501 if (req.enable && req.passive && !mPassiveSupported) {
502 LOGD("Promoting sensor %" PRIu8 " passive request to active",
503 static_cast<uint8_t>(getSensorType()));
504 }
505
506 bool success = SeeHelperSingleton::get()->makeRequest(req);
507
508 // TODO: remove setSamplingStatus when .latency is available in status update
509 // from SEE.
510 if (success) {
511 struct chreSensorSamplingStatus status;
512 if (getSamplingStatus(&status)) {
513
514 // If passive request is not supported by this SEE sensor, it won't be
515 // dynamically enabled/disabled and its status stays the same as set here.
516 if (!mPassiveSupported) {
517 status.enabled = req.enable;
518 }
519 status.latency = req.batchPeriodUs * kOneMicrosecondInNanoseconds;
520 setSamplingStatus(status);
521 }
522 }
523 return success;
524 }
525
getSensorType() const526 SensorType PlatformSensor::getSensorType() const {
527 return mSensorType;
528 }
529
getMinInterval() const530 uint64_t PlatformSensor::getMinInterval() const {
531 return mMinInterval;
532 }
533
getSensorName() const534 const char *PlatformSensor::getSensorName() const {
535 return mSensorName;
536 }
537
PlatformSensor(PlatformSensor && other)538 PlatformSensor::PlatformSensor(PlatformSensor&& other) {
539 // Our move assignment operator doesn't assume that "this" is initialized, so
540 // we can just use that here.
541 *this = std::move(other);
542 }
543
operator =(PlatformSensor && other)544 PlatformSensor& PlatformSensor::operator=(PlatformSensor&& other) {
545 // Note: if this implementation is ever changed to depend on "this" containing
546 // initialized values, the move constructor implemenation must be updated.
547 mSensorType = other.mSensorType;
548 mMinInterval = other.mMinInterval;
549 memcpy(mSensorName, other.mSensorName, kSensorNameMaxLen);
550
551 mLastEvent = other.mLastEvent;
552 other.mLastEvent = nullptr;
553
554 mLastEventSize = other.mLastEventSize;
555 other.mLastEventSize = 0;
556
557 mLastEventValid = other.mLastEventValid;
558 mSamplingStatus = other.mSamplingStatus;
559 mPassiveSupported = other.mPassiveSupported;
560
561 return *this;
562 }
563
getLastEvent() const564 ChreSensorData *PlatformSensor::getLastEvent() const {
565 return mLastEventValid ? mLastEvent : nullptr;
566 }
567
getSamplingStatus(struct chreSensorSamplingStatus * status) const568 bool PlatformSensor::getSamplingStatus(
569 struct chreSensorSamplingStatus *status) const {
570 CHRE_ASSERT(status);
571
572 memcpy(status, &mSamplingStatus, sizeof(*status));
573 return true;
574 }
575
initBase(SensorType sensorType,uint64_t minInterval,const char * sensorName,ChreSensorData * lastEvent,size_t lastEventSize,bool passiveSupported)576 void PlatformSensorBase::initBase(
577 SensorType sensorType,uint64_t minInterval, const char *sensorName,
578 ChreSensorData *lastEvent, size_t lastEventSize, bool passiveSupported) {
579 mSensorType = sensorType;
580 mMinInterval = minInterval;
581 memcpy(mSensorName, sensorName, kSensorNameMaxLen);
582 mLastEvent = lastEvent;
583 mLastEventSize = lastEventSize;
584
585 mSamplingStatus.enabled = false;
586 mSamplingStatus.interval = CHRE_SENSOR_INTERVAL_DEFAULT;
587 mSamplingStatus.latency = CHRE_SENSOR_LATENCY_DEFAULT;
588
589 mPassiveSupported = passiveSupported;
590 }
591
setLastEvent(const ChreSensorData * event)592 void PlatformSensorBase::setLastEvent(const ChreSensorData *event) {
593 memcpy(mLastEvent, event, mLastEventSize);
594 mLastEventValid = true;
595 }
596
setSamplingStatus(const struct chreSensorSamplingStatus & status)597 void PlatformSensorBase::setSamplingStatus(
598 const struct chreSensorSamplingStatus& status) {
599 mSamplingStatus = status;
600 }
601
602 } // namespace chre
603