• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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