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