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