1 /*
2 * Copyright (C) 2016 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 <general_test/basic_sensor_test_base.h>
18
19 #include <cinttypes>
20 #include <cstddef>
21
22 #include <shared/macros.h>
23 #include <shared/send_message.h>
24 #include <shared/time_util.h>
25
26 #include "chre/util/nanoapp/log.h"
27 #include "chre_api/chre.h"
28
29 #define LOG_TAG "[BasicSensorTest]"
30
31 using nanoapp_testing::kOneMillisecondInNanoseconds;
32 using nanoapp_testing::kOneSecondInNanoseconds;
33 using nanoapp_testing::MessageType;
34
35 using nanoapp_testing::sendInternalFailureToHost;
36 using nanoapp_testing::sendStringToHost;
37 using nanoapp_testing::sendSuccessToHost;
38
39 /*
40 * Our general test flow is as follows:
41 *
42 * Constructor: Send startEvent to self to start.
43 * StartEvent: Get default sensor and perform various consistency checks.
44 * Configure the sensor.
45 *
46 * At this point, it depends what kind of sensor we have for how we proceed
47 * with the test.
48 *
49 * One-shot: finishTest()
50 * On-change: Wait for one data event from sensor. Then finishTest().
51 * Continuous: Wait for two data events from sensor. Then finishTest().
52 *
53 * We also look for and perform basic consistency checking on sampling
54 * status change events, as well as bias data reports.
55 */
56
57 namespace general_test {
58
59 namespace {
60 constexpr uint16_t kStartEvent = CHRE_EVENT_FIRST_USER_VALUE;
61 constexpr uint64_t kEventLoopSlack = 100 * kOneMillisecondInNanoseconds;
62
getEventDuration(const chreSensorThreeAxisData * event)63 uint64_t getEventDuration(const chreSensorThreeAxisData *event) {
64 uint64_t duration = 0;
65 for (size_t i = 0; i < event->header.readingCount; i++) {
66 duration += event->readings[i].timestampDelta;
67 }
68
69 return duration;
70 }
71
isBiasEventType(uint16_t eventType)72 bool isBiasEventType(uint16_t eventType) {
73 return (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_BIAS_INFO) ||
74 (eventType == CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO) ||
75 (eventType == CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO);
76 }
77
78 // Helper function to call chreSensorConfigure and log the result
configureSensor(uint32_t handle,enum chreSensorConfigureMode mode,uint64_t intervalNs,uint64_t latencyNs)79 bool configureSensor(uint32_t handle, enum chreSensorConfigureMode mode,
80 uint64_t intervalNs, uint64_t latencyNs) {
81 bool success = chreSensorConfigure(handle, mode, intervalNs, latencyNs);
82 LOGI("Enabled sensor with handle %" PRIu32 " mode %d interval %" PRIu64
83 " latency %" PRIu64 " success=%d",
84 handle, mode, intervalNs, latencyNs, success);
85 return success;
86 }
87
88 } // anonymous namespace
89
BasicSensorTestBase()90 BasicSensorTestBase::BasicSensorTestBase()
91 : Test(CHRE_API_VERSION_1_0),
92 mInMethod(true),
93 mExternalSamplingStatusChange(false),
94 mState(State::kPreStart),
95 mInstanceId(chreGetInstanceId())
96 /* All other members initialized later */ {}
97
setUp(uint32_t messageSize,const void *)98 void BasicSensorTestBase::setUp(uint32_t messageSize,
99 const void * /* message */) {
100 if (messageSize != 0) {
101 EXPECT_FAIL_RETURN("Beginning message expects 0 additional bytes, got ",
102 &messageSize);
103 }
104
105 sendStartTestMessage();
106 }
107
sendStartTestMessage()108 void BasicSensorTestBase::sendStartTestMessage() {
109 mState = State::kPreStart;
110 // Most tests start running in the constructor. However, since this
111 // is a base class, and we invoke abstract methods when running our
112 // test, we don't start until after the class has been fully
113 // constructed.
114 if (!chreSendEvent(kStartEvent, nullptr, nullptr, mInstanceId)) {
115 EXPECT_FAIL_RETURN("Failed chreSendEvent to begin test");
116 }
117 mInMethod = false;
118 }
119
checkPassiveConfigure()120 void BasicSensorTestBase::checkPassiveConfigure() {
121 chreSensorConfigureMode mode =
122 isOneShotSensor() ? CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_ONE_SHOT
123 : CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS;
124
125 if (mApiVersion == CHRE_API_VERSION_1_0) {
126 // Any attempt to make a PASSIVE call with a non-default interval
127 // or latency should fail.
128 if (configureSensor(mSensorHandle, mode, CHRE_SENSOR_INTERVAL_DEFAULT,
129 999)) {
130 EXPECT_FAIL_RETURN(
131 "chreSensorConfigure() allowed passive with different latency");
132 }
133 if (configureSensor(mSensorHandle, mode, 999,
134 CHRE_SENSOR_LATENCY_DEFAULT)) {
135 EXPECT_FAIL_RETURN(
136 "chreSensorConfigure() allowed passive with different interval");
137 }
138 // TODO: In a more in-depth test, we should test passive mode
139 // receiving data. This is somewhat complicated by the fact that
140 // pretty much by definition, we don't control whether a sensor
141 // we're passively listening to is enabled or not. We could try
142 // to control this with an additional test nanoapp toggling sensor
143 // usage, but there's still the complication of other nanoapps in
144 // the system.
145 } else {
146 bool configureSuccess =
147 configureSensor(mSensorHandle, mode, CHRE_SENSOR_INTERVAL_DEFAULT,
148 kOneSecondInNanoseconds);
149 if (mSupportsPassiveMode && !configureSuccess) {
150 EXPECT_FAIL_RETURN(
151 "chreSensorConfigure() failed passive with default interval and "
152 "non-default latency");
153 } else if (!mSupportsPassiveMode && configureSuccess) {
154 EXPECT_FAIL_RETURN(
155 "chreSensorConfigure() accepted passive with default interval and "
156 "non-default latency");
157 }
158
159 if (!isOneShotSensor()) {
160 configureSuccess =
161 configureSensor(mSensorHandle, mode, kOneSecondInNanoseconds,
162 CHRE_SENSOR_LATENCY_DEFAULT);
163 if (mSupportsPassiveMode && !configureSuccess) {
164 EXPECT_FAIL_RETURN(
165 "chreSensorConfigure() failed passive with non-default interval "
166 "and default latency");
167 } else if (!mSupportsPassiveMode && configureSuccess) {
168 EXPECT_FAIL_RETURN(
169 "chreSensorConfigure() accepted passive with non-default "
170 "interval and default latency");
171 }
172
173 configureSuccess =
174 configureSensor(mSensorHandle, mode, kOneSecondInNanoseconds,
175 kOneSecondInNanoseconds);
176 if (mSupportsPassiveMode && !configureSuccess) {
177 EXPECT_FAIL_RETURN(
178 "chreSensorConfigure() failed passive with non-default interval "
179 "and latency");
180 } else if (!mSupportsPassiveMode && configureSuccess) {
181 EXPECT_FAIL_RETURN(
182 "chreSensorConfigure() accepted passive with non-default interval "
183 "and latency");
184 }
185 }
186 }
187 }
188
startTest()189 void BasicSensorTestBase::startTest() {
190 mState = State::kPreConfigure;
191
192 bool found = false;
193 uint8_t mSensorType = getSensorType();
194 // TODO(b/286604767): CHRE should only expose the default light sensor to
195 // nanoapps.
196 if (mApiVersion >= CHRE_API_VERSION_1_5 &&
197 mSensorType != CHRE_SENSOR_TYPE_LIGHT) {
198 found = chreSensorFind(mSensorType, mCurrentSensorIndex, &mSensorHandle);
199 if (!found &&
200 chreSensorFind(mSensorType, mCurrentSensorIndex + 1, &mSensorHandle)) {
201 EXPECT_FAIL_RETURN_UINT8("Missing sensor index ", mCurrentSensorIndex);
202 return;
203 }
204 } else {
205 found = chreSensorFindDefault(mSensorType, &mSensorHandle);
206 }
207
208 if (!found) {
209 sendStringToHost(MessageType::kSkipped,
210 "No default sensor found for optional sensor.");
211 return;
212 }
213
214 LOGI("Starting test for sensor index %" PRIu8, mCurrentSensorIndex);
215
216 chreSensorInfo info;
217 if (!chreGetSensorInfo(mSensorHandle, &info)) {
218 EXPECT_FAIL_RETURN("GetSensorInfo() call failed");
219 }
220 if (info.sensorName == nullptr) {
221 EXPECT_FAIL_RETURN("chreSensorInfo::sensorName is NULL");
222 }
223 if (info.sensorType != mSensorType) {
224 uint32_t type = info.sensorType;
225 EXPECT_FAIL_RETURN("chreSensorInfo::sensorType is not expected value, is:",
226 &type);
227 }
228 if (info.isOnChange != isOnChangeSensor()) {
229 EXPECT_FAIL_RETURN(
230 "chreSensorInfo::isOnChange is opposite of what we expected");
231 }
232 if (info.isOneShot != isOneShotSensor()) {
233 EXPECT_FAIL_RETURN(
234 "chreSensorInfo::isOneShot is opposite of what we expected");
235 }
236 if (mApiVersion >= CHRE_API_VERSION_1_4) {
237 mSupportsPassiveMode = info.supportsPassiveMode;
238 } else if (info.supportsPassiveMode != 0) {
239 EXPECT_FAIL_RETURN("chreSensorInfo::supportsPassiveMode should be 0");
240 }
241
242 if (!chreGetSensorSamplingStatus(mSensorHandle, &mOriginalStatus)) {
243 EXPECT_FAIL_RETURN("chreGetSensorSamplingStatus() failed");
244 } else {
245 LOGI("Original sampling status interval=%" PRIu64 " latency=%" PRIu64
246 " enabled %d",
247 mOriginalStatus.interval, mOriginalStatus.latency,
248 mOriginalStatus.enabled);
249 }
250
251 // Set the base timestamp to compare against before configuring the sensor.
252 mPreTimestamp = chreGetTime();
253
254 // Default interval/latency must be accepted by all sensors.
255 mNewStatus = {
256 CHRE_SENSOR_INTERVAL_DEFAULT, /* interval */
257 CHRE_SENSOR_LATENCY_DEFAULT, /* latency */
258 true /* enabled */
259 };
260 chreSensorConfigureMode mode = isOneShotSensor()
261 ? CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT
262 : CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS;
263
264 if (!configureSensor(mSensorHandle, mode, mNewStatus.interval,
265 mNewStatus.latency)) {
266 EXPECT_FAIL_RETURN(
267 "chreSensorConfigure() call failed with default interval and latency");
268 }
269
270 // handleEvent may start getting events, and our testing continues there.
271 // (Note: The CHRE is not allow to call handleEvent() while we're still
272 // in this method, so it's not a race to set this state here.)
273
274 // Set a new request so the test can receive events before test timeout.
275 mNewStatus = {
276 // This will be valid on all required sensors.
277 // TODO: A more in-depth test could try to change this interval
278 // from what it currently is for the sensor, and confirm it
279 // changes back when we're DONE. But that's beyond the current
280 // scope of this 'basic' test.
281 kOneSecondInNanoseconds, /* interval */
282 // We want the test to run as quickly as possible.
283 // TODO: Similar to the interval, we could try to test changes in
284 // this value, but it's beyond our 'basic' scope for now.
285 CHRE_SENSOR_LATENCY_ASAP, /* latency */
286 true /* enabled */
287 };
288
289 // Skip one-shot sensors for non-default interval configurations.
290 if (!isOneShotSensor() &&
291 !configureSensor(mSensorHandle, mode, mNewStatus.interval,
292 mNewStatus.latency)) {
293 EXPECT_FAIL_RETURN("chreSensorConfigure() call failed");
294 }
295
296 if (isOnChangeSensor()) {
297 // We should receive the current state of this sensor after the
298 // configure call. However, we're not assured additional events,
299 // since we don't know if this is going to change. Thus, we jump
300 // our testing state to waiting for the last event.
301 mState = State::kExpectingLastDataEvent;
302 } else if (isOneShotSensor()) {
303 // There's no assurance we'll get any events from a one-shot
304 // sensor, so we'll just skip to the end of the test.
305 finishTest();
306 } else {
307 mState = State::kExpectingInitialDataEvent;
308 }
309 }
310
finishTest()311 void BasicSensorTestBase::finishTest() {
312 checkPassiveConfigure();
313
314 if (!chreSensorConfigureModeOnly(mSensorHandle,
315 CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
316 EXPECT_FAIL_RETURN("Unable to configure sensor mode to DONE");
317 } else {
318 LOGI("Successfully disabled sensor");
319 }
320 mDoneTimestamp = chreGetTime();
321 chreSensorSamplingStatus status;
322 if (!chreGetSensorSamplingStatus(mSensorHandle, &status)) {
323 EXPECT_FAIL_RETURN("Could not get final sensor info");
324 }
325 LOGI("Final sampling status interval=%" PRIu64 " latency=%" PRIu64
326 " enabled %d",
327 status.interval, status.latency, status.enabled);
328 if (!mExternalSamplingStatusChange) {
329 // No one else changed this, so it should be what we had before.
330 if (status.enabled != mOriginalStatus.enabled) {
331 EXPECT_FAIL_RETURN("SensorInfo.enabled not back to original");
332 }
333 // Interval and latency values are only relevent if the sensor is enabled.
334 if (status.enabled) {
335 if (status.interval != mOriginalStatus.interval) {
336 EXPECT_FAIL_RETURN("SensorInfo.interval not back to original");
337 }
338 if (status.latency != mOriginalStatus.latency) {
339 EXPECT_FAIL_RETURN("SensorInfo.latency not back to original");
340 }
341 }
342 }
343
344 LOGI("Test passed for sensor index %" PRIu8, mCurrentSensorIndex);
345
346 bool finished = true;
347 if (mApiVersion >= CHRE_API_VERSION_1_5) {
348 mCurrentSensorIndex++;
349 // TODO(b/286604767): CHRE should only expose the default light sensor to
350 // nanoapps.
351 uint32_t sensorHandle;
352 uint8_t mSensorType = getSensorType();
353 if (mSensorType != CHRE_SENSOR_TYPE_LIGHT &&
354 chreSensorFind(getSensorType(), mCurrentSensorIndex, &sensorHandle)) {
355 finished = false;
356 mPrevSensorHandle = mSensorHandle;
357 sendStartTestMessage();
358 }
359 }
360
361 if (finished) {
362 mState = State::kFinished;
363 sendSuccessToHost();
364 }
365 }
366
verifyEventHeader(const chreSensorDataHeader * header,uint16_t eventType,uint64_t eventDuration)367 void BasicSensorTestBase::verifyEventHeader(const chreSensorDataHeader *header,
368 uint16_t eventType,
369 uint64_t eventDuration) {
370 if (header->sensorHandle != mSensorHandle) {
371 EXPECT_FAIL_RETURN("SensorDataHeader for wrong handle",
372 &header->sensorHandle);
373 }
374
375 // Bias and on-change sensor events may have timestamps from before any of our
376 // requests started since they aren't generated in response to requests. For
377 // these types of events, only ensure the provided timestamp is less than the
378 // current time.
379 if (!isOnChangeSensor() && !isBiasEventType(eventType)) {
380 // An on-change sensor is supposed to send its current state, which
381 // could be timestamped in the past. Everything else should be
382 // getting recent data.
383 uint64_t *minTime = nullptr;
384 uint64_t *timeToUpdate = nullptr;
385
386 if (mState == State::kExpectingInitialDataEvent) {
387 minTime = &mPreTimestamp;
388 timeToUpdate = &mFirstEventTimestamp;
389 } else if (mState == State::kExpectingLastDataEvent) {
390 minTime = &mFirstEventTimestamp;
391 timeToUpdate = &mLastEventTimestamp;
392 } else { // State::kFinished
393 minTime = &mLastEventTimestamp;
394 // Go ahead and update this timestamp again.
395 timeToUpdate = &mLastEventTimestamp;
396 }
397
398 // If there's another CHRE client requesting batched sensor data,
399 // baseTimestamp can be before mPreTimestamp. Also allow
400 // kEventLoopSlack to handle this nanoapp before handling the sensor
401 // event.
402 uint64_t minTimeWithSlack =
403 (*minTime > eventDuration + kEventLoopSlack)
404 ? (*minTime - eventDuration - kEventLoopSlack)
405 : 0;
406 if (header->baseTimestamp < minTimeWithSlack) {
407 LOGE("baseTimestamp %" PRIu64 " < minTimeWithSlack %" PRIu64
408 ": minTime %" PRIu64 " eventDuration %" PRIu64
409 " kEventLoopSlack %" PRIu64,
410 header->baseTimestamp, minTimeWithSlack, *minTime, eventDuration,
411 kEventLoopSlack);
412 EXPECT_FAIL_RETURN("SensorDataHeader is in the past");
413 }
414 if ((mState == State::kFinished) &&
415 (header->baseTimestamp > mDoneTimestamp)) {
416 EXPECT_FAIL_RETURN("SensorDataHeader is from after DONE");
417 }
418 *timeToUpdate = header->baseTimestamp;
419 }
420
421 if (header->baseTimestamp > chreGetTime()) {
422 EXPECT_FAIL_RETURN("SensorDataHeader is in the future");
423 }
424
425 if (header->readingCount == 0) {
426 EXPECT_FAIL_RETURN("SensorDataHeader has readingCount of 0");
427 }
428
429 if (header->reserved != 0) {
430 EXPECT_FAIL_RETURN("SensorDataHeader has non-zero reserved field");
431 }
432
433 if (mApiVersion < CHRE_API_VERSION_1_3) {
434 if (header->accuracy != 0) {
435 EXPECT_FAIL_RETURN("SensorDataHeader has non-zero reserved field");
436 }
437 } else if (header->accuracy > CHRE_SENSOR_ACCURACY_HIGH) {
438 EXPECT_FAIL_RETURN_UINT8("Sensor accuracy is not within valid range: ",
439 header->accuracy);
440 }
441 }
442
handleBiasEvent(uint16_t eventType,const chreSensorThreeAxisData * eventData)443 void BasicSensorTestBase::handleBiasEvent(
444 uint16_t eventType, const chreSensorThreeAxisData *eventData) {
445 uint8_t expectedSensorType = 0;
446 uint32_t eType = eventType;
447 if (eventType == CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO) {
448 expectedSensorType = CHRE_SENSOR_TYPE_GYROSCOPE;
449 } else if (eventType == CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO) {
450 expectedSensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
451 } else if (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_BIAS_INFO) {
452 expectedSensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
453 } else {
454 sendInternalFailureToHost("Illegal eventType in handleBiasEvent", &eType);
455 }
456
457 if (expectedSensorType != getSensorType()) {
458 EXPECT_FAIL_RETURN("Unexpected bias event:", &eType);
459 }
460 verifyEventHeader(&eventData->header, eventType, getEventDuration(eventData));
461
462 // TODO: consistency check the eventData. This check is out-of-scope for
463 // Android N testing.
464 }
465
handleSamplingChangeEvent(const chreSensorSamplingStatusEvent * eventData)466 void BasicSensorTestBase::handleSamplingChangeEvent(
467 const chreSensorSamplingStatusEvent *eventData) {
468 LOGI("handleSamplingChangeEvent interval=%" PRIu64 " latency=%" PRIu64
469 " enabled=%d",
470 eventData->status.interval, eventData->status.latency,
471 eventData->status.enabled);
472 if (mPrevSensorHandle.has_value() &&
473 (mPrevSensorHandle.value() == eventData->sensorHandle)) {
474 // We can get a "DONE" event from the previous sensor for multi-sensor
475 // devices, so we ignore these events.
476 return;
477 }
478
479 if (eventData->sensorHandle != mSensorHandle) {
480 EXPECT_FAIL_RETURN("SamplingChangeEvent for wrong sensor handle:",
481 &eventData->sensorHandle);
482 }
483
484 // TODO: If we strictly define whether this event is or isn't
485 // generated upon being DONE with a sensor, then we can perform
486 // a strict check here. For now, we just let this go.
487 if (mState != State::kFinished) {
488 // We received a sensor disabled status change event. While it's not
489 // expected, it's possible we received an event that was originated prior to
490 // the test run, so we just log a warning rather than failing the test.
491 if (!eventData->status.enabled) {
492 LOGW("SamplingChangeEvent disabled the sensor.");
493 }
494
495 if ((mNewStatus.interval != eventData->status.interval) ||
496 (mNewStatus.latency != eventData->status.latency)) {
497 // This is from someone other than us. Let's note that so we know
498 // our consistency checks are invalid.
499 mExternalSamplingStatusChange = true;
500 }
501 }
502 }
503
handleSensorDataEvent(uint16_t eventType,const void * eventData)504 void BasicSensorTestBase::handleSensorDataEvent(uint16_t eventType,
505 const void *eventData) {
506 if ((mState == State::kPreStart) || (mState == State::kPreConfigure)) {
507 EXPECT_FAIL_RETURN("SensorDataEvent sent too early.");
508 }
509 // Note, if mState is kFinished, we could be getting batched data which
510 // hadn't been delivered yet at the time we were DONE. We'll consistency
511 // check it, even though in theory we're done testing.
512 uint64_t eventDuration =
513 getEventDuration(static_cast<const chreSensorThreeAxisData *>(eventData));
514 verifyEventHeader(static_cast<const chreSensorDataHeader *>(eventData),
515 eventType, eventDuration);
516
517 // Send to the sensor itself for any additional checks of actual data.
518 confirmDataIsSane(eventData);
519 if (mState == State::kExpectingInitialDataEvent) {
520 mState = State::kExpectingLastDataEvent;
521 } else if (mState == State::kExpectingLastDataEvent) {
522 finishTest();
523 } else if (mState != State::kFinished) {
524 uint32_t value = static_cast<uint32_t>(mState);
525 sendInternalFailureToHost("Illegal mState in handleSensorDataEvent:",
526 &value);
527 }
528 }
529
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)530 void BasicSensorTestBase::handleEvent(uint32_t senderInstanceId,
531 uint16_t eventType,
532 const void *eventData) {
533 if (mInMethod) {
534 EXPECT_FAIL_RETURN("handleEvent() invoked while already in method.");
535 }
536 mInMethod = true;
537 const uint16_t dataEventType =
538 CHRE_EVENT_SENSOR_DATA_EVENT_BASE + getSensorType();
539
540 if (senderInstanceId == mInstanceId) {
541 if ((eventType == kStartEvent) && (mState == State::kPreStart)) {
542 startTest();
543 }
544 } else if (senderInstanceId != CHRE_INSTANCE_ID) {
545 EXPECT_FAIL_RETURN("Unexpected senderInstanceId:", &senderInstanceId);
546
547 } else if (eventData == nullptr) {
548 uint32_t eType = eventType;
549 EXPECT_FAIL_RETURN("Got NULL eventData for event:", &eType);
550
551 } else if (eventType == dataEventType) {
552 handleSensorDataEvent(eventType, eventData);
553
554 } else if (eventType == CHRE_EVENT_SENSOR_SAMPLING_CHANGE) {
555 handleSamplingChangeEvent(
556 static_cast<const chreSensorSamplingStatusEvent *>(eventData));
557
558 } else if (isBiasEventType(eventType)) {
559 handleBiasEvent(eventType,
560 static_cast<const chreSensorThreeAxisData *>(eventData));
561
562 } else {
563 unexpectedEvent(eventType);
564 }
565
566 mInMethod = false;
567 }
568
569 } // namespace general_test
570