1 /*
2  * Copyright (C) 2019 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_flush_async_test.h>
18 
19 #include <cinttypes>
20 
21 #include <shared/macros.h>
22 #include <shared/send_message.h>
23 #include <shared/time_util.h>
24 
25 using nanoapp_testing::kOneMillisecondInNanoseconds;
26 using nanoapp_testing::kOneSecondInNanoseconds;
27 using nanoapp_testing::sendFatalFailureToHost;
28 using nanoapp_testing::sendSuccessToHost;
29 
30 namespace general_test {
31 
setUp(uint32_t messageSize,const void * message)32 void BasicSensorFlushAsyncTest::setUp(uint32_t messageSize,
33                                       const void *message) {
34   constexpr uint64_t kFlushTestLatencyNs = 2 * kOneSecondInNanoseconds;
35   constexpr uint64_t kFlushTestStartTimerValueNs =
36       kFlushTestLatencyNs / 2;  // start the test at (now + 1/2*latency)
37 
38   if (messageSize != 0) {
39     sendFatalFailureToHost("Expected 0 byte message, got more bytes:",
40                            &messageSize);
41   }
42 
43   // TODO: Generalize this test for all sensors by making
44   // BasicSensorFlushAsyncTest a base class for sensor specific tests for the
45   // FlushAsync API
46   if (!chreSensorFindDefault(CHRE_SENSOR_TYPE_ACCELEROMETER, &mSensorHandle)) {
47     sendFatalFailureToHost("Default Accelerometer not found");
48   }
49 
50   // We set the sampling period of the sensor to 2x the min interval,
51   // and set a variable to track that we get sensor samples within a
52   // reasonable (a small order of magnitude greater than the min interval)
53   // 'wiggle room' from when we start the flush request.
54   struct chreSensorInfo info;
55   if (!chreGetSensorInfo(mSensorHandle, &info)) {
56     sendFatalFailureToHost("Failed to get sensor info");
57   }
58   mFlushTestTimeWiggleRoomNs = 20 * info.minInterval;
59 
60   if (!chreSensorConfigure(mSensorHandle, CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS,
61                            2 * info.minInterval, kFlushTestLatencyNs)) {
62     sendFatalFailureToHost("Failed to configure the accelerometer");
63   }
64 
65   // To exercise the test, we need to confirm that we actually get sensor
66   // samples from the flush request. to do this, set a timer to start a flush
67   // request at around latency/2 time from now, and request the flush when it
68   // expires, hoping to receive some of the data accumulated between configure
69   // time and flush request time
70   mFlushStartTimerHandle =
71       chreTimerSet(kFlushTestStartTimerValueNs, &mFlushStartTimerHandle,
72                    true /* one shot */);
73   if (CHRE_TIMER_INVALID == mFlushStartTimerHandle) {
74     sendFatalFailureToHost("Failed to set flush start timer");
75   }
76 }
77 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)78 void BasicSensorFlushAsyncTest::handleEvent(uint32_t senderInstanceId,
79                                             uint16_t eventType,
80                                             const void *eventData) {
81   switch (eventType) {
82     case CHRE_EVENT_SENSOR_ACCELEROMETER_DATA:
83       handleDataReceived(
84           static_cast<const struct chreSensorThreeAxisData *>(eventData));
85       break;
86 
87     case CHRE_EVENT_SENSOR_FLUSH_COMPLETE:
88       handleFlushComplete(
89           static_cast<const struct chreSensorFlushCompleteEvent *>(eventData));
90       break;
91 
92     case CHRE_EVENT_TIMER:
93       handleTimerExpired(static_cast<const uint32_t *>(eventData));
94       break;
95 
96     default:
97       break;
98   }
99 }
100 
start()101 void BasicSensorFlushAsyncTest::start() {
102   mStarted = true;
103   mFlushRequestTime = chreGetTime();
104 
105   if (!chreSensorFlushAsync(mSensorHandle, &mCookie)) {
106     finish(false /* succeeded */, "Async flush failed");
107   }
108 
109   mFlushTimeoutTimerHandle =
110       chreTimerSet(CHRE_SENSOR_FLUSH_COMPLETE_TIMEOUT_NS,
111                    &mFlushTimeoutTimerHandle, true /* oneShot */);
112   if (CHRE_TIMER_INVALID == mFlushTimeoutTimerHandle) {
113     sendFatalFailureToHost("Failed to set flush start timer");
114   }
115 }
116 
finish(bool succeeded,const char * message)117 void BasicSensorFlushAsyncTest::finish(bool succeeded, const char *message) {
118   mStarted = false;
119 
120   if (mFlushTimeoutTimerHandle != CHRE_TIMER_INVALID) {
121     chreTimerCancel(mFlushTimeoutTimerHandle);
122   }
123 
124   if (!chreSensorConfigureModeOnly(mSensorHandle,
125                                    CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
126     sendFatalFailureToHost("Failed to release sensor handle");
127   }
128 
129   if (!succeeded) {
130     ASSERT_NE(message, nullptr, "message cannot be null when the test failed");
131     sendFatalFailureToHost(message);
132   } else {
133     sendSuccessToHost();
134   }
135 }
136 
handleDataReceived(const struct chreSensorThreeAxisData * eventData)137 void BasicSensorFlushAsyncTest::handleDataReceived(
138     const struct chreSensorThreeAxisData *eventData) {
139   // we're only interested in storing the latest timestamp of the sensor data
140   mLatestSensorDataTimestamp = eventData->header.baseTimestamp;
141   for (int i = 0; i < eventData->header.readingCount; ++i) {
142     mLatestSensorDataTimestamp += eventData->readings[i].timestampDelta;
143   }
144 }
145 
handleFlushComplete(const struct chreSensorFlushCompleteEvent * eventData)146 void BasicSensorFlushAsyncTest::handleFlushComplete(
147     const struct chreSensorFlushCompleteEvent *eventData) {
148   if (mStarted) {
149     ASSERT_NE(mLatestSensorDataTimestamp, 0, "No sensor data was received");
150 
151     // we should fail the test if we receive too old a sensor sample.
152     // ideally, we don't receive any samples that was sampled after
153     // our flush request, but for this test, we'll be lenient and assume
154     // that anything between [flushRequestTime - kFlushTestTimeWiggleRoomNs,
155     // now] is OK.
156     uint64_t oldestValidTimestamp =
157         mFlushRequestTime - mFlushTestTimeWiggleRoomNs;
158 
159     ASSERT_GE(mLatestSensorDataTimestamp, oldestValidTimestamp,
160               "Received very old data");
161 
162     chreLog(CHRE_LOG_INFO,
163             "Flush test: flush request to complete time: %" PRIu64 " ms",
164             (chreGetTime() - mFlushRequestTime) / kOneMillisecondInNanoseconds);
165 
166     // verify event data
167     ASSERT_NE(eventData, nullptr, "null event data");
168     ASSERT_EQ(eventData->sensorHandle, mSensorHandle,
169               "Got flush event from a different sensor handle");
170     ASSERT_EQ(eventData->errorCode, CHRE_ERROR_NONE,
171               "Flush Error code was not CHRE_ERROR_NONE");
172     ASSERT_NE(eventData->cookie, nullptr,
173               "Null cookie in flush complete event");
174     ASSERT_EQ(*(static_cast<const uint32_t *>(eventData->cookie)), mCookie,
175               "unexpected cookie in flush complete event");
176 
177     finish(true /* succeeded */, nullptr /* message */);
178   }
179 }
180 
handleTimerExpired(const uint32_t * timerHandle)181 void BasicSensorFlushAsyncTest::handleTimerExpired(
182     const uint32_t *timerHandle) {
183   if (timerHandle != nullptr) {
184     if (mFlushStartTimerHandle == *timerHandle) {
185       start();
186     } else if (mFlushTimeoutTimerHandle == *timerHandle) {
187       finish(false /* succeeded */,
188              "Did not receive flush complete event in time");
189     } else {
190       sendFatalFailureToHost("Unexpected timer handle received");
191     }
192   } else {
193     sendFatalFailureToHost("Null timer handle received");
194   }
195 }
196 
197 }  // namespace general_test