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