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