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