1 /*
2 * Copyright (C) 2021 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 "chre_stress_test_manager.h"
18
19 #include <pb_decode.h>
20 #include <pb_encode.h>
21
22 #include "chre/util/macros.h"
23 #include "chre/util/memory.h"
24 #include "chre/util/nanoapp/audio.h"
25 #include "chre/util/nanoapp/ble.h"
26 #include "chre/util/nanoapp/callbacks.h"
27 #include "chre/util/nanoapp/log.h"
28 #include "chre/util/unique_ptr.h"
29 #include "chre_stress_test.nanopb.h"
30 #include "send_message.h"
31
32 #define LOG_TAG "[ChreStressTest]"
33
34 using chre::kOneMicrosecondInNanoseconds;
35 using chre::kOneMillisecondInNanoseconds;
36 using chre::ble_constants::kNumScanFilters;
37
38 namespace chre {
39
40 namespace stress_test {
41
42 namespace {
43
44 //! Additional duration to handle request timeout over the specified
45 //! CHRE API timeout (to account for processing delay).
46 #define TIMEOUT_BUFFER_DELAY_NS (1 * CHRE_NSEC_PER_SEC)
47
48 constexpr chre::Nanoseconds kWifiScanInterval = chre::Seconds(5);
49 constexpr chre::Nanoseconds kSensorRequestInterval = chre::Seconds(5);
50 constexpr chre::Nanoseconds kAudioRequestInterval = chre::Seconds(5);
51 constexpr chre::Nanoseconds kBleRequestInterval = chre::Milliseconds(50);
52 constexpr uint64_t kSensorSamplingDelayNs = 0;
53 constexpr uint8_t kAccelSensorIndex = 0;
54 constexpr uint8_t kGyroSensorIndex = 1;
55 constexpr uint8_t kInstantMotionSensorIndex = 1;
56
57 //! Report delay for BLE scans.
58 constexpr uint32_t kBleBatchDurationMs = 0;
59
isRequestTypeForLocation(uint8_t requestType)60 bool isRequestTypeForLocation(uint8_t requestType) {
61 return (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START) ||
62 (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP);
63 }
64
isRequestTypeForMeasurement(uint8_t requestType)65 bool isRequestTypeForMeasurement(uint8_t requestType) {
66 return (requestType == CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_START) ||
67 (requestType == CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP);
68 }
69
70 } // anonymous namespace
71
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)72 void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
73 const void *eventData) {
74 if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
75 handleMessageFromHost(
76 senderInstanceId,
77 static_cast<const chreMessageFromHostData *>(eventData));
78 } else if (senderInstanceId == CHRE_INSTANCE_ID) {
79 handleDataFromChre(eventType, eventData);
80 } else {
81 LOGW("Got unknown event type from senderInstanceId %" PRIu32
82 " and with eventType %" PRIu16,
83 senderInstanceId, eventType);
84 }
85 }
86
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)87 void Manager::handleMessageFromHost(uint32_t senderInstanceId,
88 const chreMessageFromHostData *hostData) {
89 bool success = false;
90 uint32_t messageType = hostData->messageType;
91 if (senderInstanceId != CHRE_INSTANCE_ID) {
92 LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
93 } else if (messageType == chre_stress_test_MessageType_TEST_HOST_RESTARTED) {
94 // Do nothing and only update the host endpoint
95 mHostEndpoint = hostData->hostEndpoint;
96 success = true;
97 } else if (messageType == chre_stress_test_MessageType_GET_CAPABILITIES) {
98 sendCapabilitiesMessage();
99 success = true;
100 } else if (messageType != chre_stress_test_MessageType_TEST_COMMAND) {
101 LOGE("Invalid message type %" PRIu32, messageType);
102 } else if (mHostEndpoint.has_value() &&
103 hostData->hostEndpoint != mHostEndpoint.value()) {
104 LOGE("Invalid host endpoint %" PRIu16 " expected %" PRIu16,
105 hostData->hostEndpoint, mHostEndpoint.value());
106 } else {
107 pb_istream_t istream = pb_istream_from_buffer(
108 static_cast<const pb_byte_t *>(hostData->message),
109 hostData->messageSize);
110 chre_stress_test_TestCommand testCommand =
111 chre_stress_test_TestCommand_init_default;
112
113 if (!pb_decode(&istream, chre_stress_test_TestCommand_fields,
114 &testCommand)) {
115 LOGE("Failed to decode start command error %s", PB_GET_ERROR(&istream));
116 } else {
117 LOGI("Got message from host: feature %d start %d", testCommand.feature,
118 testCommand.start);
119
120 success = true;
121 switch (testCommand.feature) {
122 case chre_stress_test_TestCommand_Feature_WIFI_ON_DEMAND_SCAN: {
123 handleWifiStartCommand(testCommand.start);
124 break;
125 }
126 case chre_stress_test_TestCommand_Feature_GNSS_LOCATION: {
127 handleGnssLocationStartCommand(testCommand.start);
128 break;
129 }
130 case chre_stress_test_TestCommand_Feature_GNSS_MEASUREMENT: {
131 handleGnssMeasurementStartCommand(testCommand.start);
132 break;
133 }
134 case chre_stress_test_TestCommand_Feature_WWAN: {
135 handleWwanStartCommand(testCommand.start);
136 break;
137 }
138 case chre_stress_test_TestCommand_Feature_WIFI_SCAN_MONITOR: {
139 handleWifiScanMonitoringCommand(testCommand.start);
140 break;
141 }
142 case chre_stress_test_TestCommand_Feature_SENSORS: {
143 handleSensorStartCommand(testCommand.start);
144 break;
145 }
146 case chre_stress_test_TestCommand_Feature_AUDIO: {
147 handleAudioStartCommand(testCommand.start);
148 break;
149 }
150 case chre_stress_test_TestCommand_Feature_BLE: {
151 handleBleStartCommand(testCommand.start);
152 break;
153 }
154 default: {
155 LOGE("Unknown feature %d", testCommand.feature);
156 success = false;
157 break;
158 }
159 }
160 }
161
162 mHostEndpoint = hostData->hostEndpoint;
163 }
164
165 if (!success) {
166 test_shared::sendTestResultWithMsgToHost(
167 hostData->hostEndpoint,
168 chre_stress_test_MessageType_TEST_RESULT /* messageType */, success,
169 nullptr /* errMessage */);
170 }
171 }
172
handleDataFromChre(uint16_t eventType,const void * eventData)173 void Manager::handleDataFromChre(uint16_t eventType, const void *eventData) {
174 switch (eventType) {
175 case CHRE_EVENT_TIMER:
176 handleTimerEvent(static_cast<const uint32_t *>(eventData));
177 break;
178
179 case CHRE_EVENT_WIFI_ASYNC_RESULT:
180 handleWifiAsyncResult(static_cast<const chreAsyncResult *>(eventData));
181 break;
182
183 case CHRE_EVENT_WIFI_SCAN_RESULT:
184 handleWifiScanEvent(static_cast<const chreWifiScanEvent *>(eventData));
185 break;
186
187 case CHRE_EVENT_GNSS_ASYNC_RESULT:
188 handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData));
189 break;
190
191 case CHRE_EVENT_GNSS_LOCATION:
192 handleGnssLocationEvent(
193 static_cast<const chreGnssLocationEvent *>(eventData));
194 break;
195
196 case CHRE_EVENT_GNSS_DATA:
197 handleGnssDataEvent(static_cast<const chreGnssDataEvent *>(eventData));
198 break;
199
200 case CHRE_EVENT_WWAN_CELL_INFO_RESULT:
201 handleCellInfoResult(
202 static_cast<const chreWwanCellInfoResult *>(eventData));
203 break;
204
205 case CHRE_EVENT_SENSOR_ACCELEROMETER_DATA:
206 handleAccelSensorDataEvent(
207 static_cast<const chreSensorThreeAxisData *>(eventData));
208 break;
209
210 case CHRE_EVENT_SENSOR_GYROSCOPE_DATA:
211 handleGyroSensorDataEvent(
212 static_cast<const chreSensorThreeAxisData *>(eventData));
213 break;
214
215 case CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA:
216 handleInstantMotionSensorDataEvent(
217 static_cast<const chreSensorOccurrenceData *>(eventData));
218 break;
219
220 case CHRE_EVENT_SENSOR_SAMPLING_CHANGE:
221 handleSensorSamplingChangeEvent(
222 static_cast<const chreSensorSamplingStatusEvent *>(eventData));
223 break;
224
225 case CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO:
226 LOGI("Received gyro bias info");
227 break;
228
229 case CHRE_EVENT_AUDIO_DATA:
230 handleAudioDataEvent(static_cast<const chreAudioDataEvent *>(eventData));
231 break;
232
233 case CHRE_EVENT_AUDIO_SAMPLING_CHANGE:
234 handleAudioSamplingChangeEvent(
235 static_cast<const chreAudioSourceStatusEvent *>(eventData));
236 break;
237
238 case CHRE_EVENT_BLE_ADVERTISEMENT:
239 handleBleAdvertismentEvent(
240 static_cast<const chreBleAdvertisementEvent *>(eventData));
241 break;
242
243 case CHRE_EVENT_BLE_ASYNC_RESULT:
244 handleBleAsyncResult(static_cast<const chreAsyncResult *>(eventData));
245 break;
246
247 default:
248 LOGW("Unknown event type %" PRIu16, eventType);
249 break;
250 }
251 }
252
handleTimerEvent(const uint32_t * handle)253 void Manager::handleTimerEvent(const uint32_t *handle) {
254 if (*handle == mWifiScanTimerHandle) {
255 handleDelayedWifiTimer();
256 } else if (*handle == mWifiScanAsyncTimerHandle) {
257 sendFailure("WiFi scan request timed out");
258 } else if (*handle == mGnssLocationTimerHandle) {
259 makeGnssLocationRequest();
260 } else if (*handle == mGnssMeasurementTimerHandle) {
261 makeGnssMeasurementRequest();
262 } else if (*handle == mSensorTimerHandle) {
263 makeSensorRequests();
264 } else if (*handle == mGnssLocationAsyncTimerHandle &&
265 mGnssLocationAsyncRequest.has_value()) {
266 sendFailure("GNSS location async result timed out");
267 } else if (*handle == mGnssMeasurementAsyncTimerHandle &&
268 mGnssMeasurementAsyncRequest.has_value()) {
269 sendFailure("GNSS measurement async result timed out");
270 } else if (*handle == mWwanTimerHandle) {
271 makeWwanCellInfoRequest();
272 } else if (*handle == mBleScanTimerHandle) {
273 makeBleScanRequest();
274 } else if (*handle == mWifiScanMonitorAsyncTimerHandle) {
275 sendFailure("WiFi scan monitor request timed out");
276 } else if (*handle == mAudioTimerHandle) {
277 makeAudioRequest();
278 } else {
279 sendFailure("Unknown timer handle");
280 }
281 }
282
handleDelayedWifiTimer()283 void Manager::handleDelayedWifiTimer() {
284 // NOTE: We set the maxScanAgeMs to something smaller than the WiFi
285 // scan periodicity to ensure new scans are generated.
286 static const struct chreWifiScanParams params = {
287 /*.scanType=*/CHRE_WIFI_SCAN_TYPE_NO_PREFERENCE,
288 /*.maxScanAgeMs=*/2000, // 2 seconds
289 /*.frequencyListLen=*/0,
290 /*.frequencyList=*/NULL,
291 /*.ssidListLen=*/0,
292 /*.ssidList=*/NULL,
293 /*.radioChainPref=*/CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT,
294 /*.channelSet=*/CHRE_WIFI_CHANNEL_SET_NON_DFS};
295
296 bool success = chreWifiRequestScanAsync(¶ms, &kOnDemandWifiScanCookie);
297 LOGI("Requested on demand wifi success ? %d", success);
298 if (!success) {
299 sendFailure("Failed to make WiFi scan request");
300 } else {
301 mWifiScanAsyncRequest = AsyncRequest(&kOnDemandWifiScanCookie);
302 setTimer(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
303 true /* oneShot */, &mWifiScanAsyncTimerHandle);
304 }
305 }
306
handleWifiAsyncResult(const chreAsyncResult * result)307 void Manager::handleWifiAsyncResult(const chreAsyncResult *result) {
308 if (result->requestType == CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN) {
309 if (result->success) {
310 LOGI("On-demand scan success");
311 } else {
312 LOGW("On-demand scan failed: code %" PRIu8, result->errorCode);
313 }
314
315 if (!mWifiScanAsyncRequest.has_value()) {
316 sendFailure("Received WiFi async result with no pending request");
317 } else if (result->cookie != mWifiScanAsyncRequest->cookie) {
318 sendFailure("On-demand scan cookie mismatch");
319 }
320
321 cancelTimer(&mWifiScanAsyncTimerHandle);
322 mWifiScanAsyncRequest.reset();
323 requestDelayedWifiScan();
324 } else if (result->requestType ==
325 CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR) {
326 if (!result->success) {
327 LOGE("Scan monitor async failure: code %" PRIu8, result->errorCode);
328 sendFailure("Scan monitor async failed");
329 }
330
331 cancelTimer(&mWifiScanMonitorAsyncTimerHandle);
332 mWifiScanMonitorEnabled = (result->cookie != nullptr);
333 } else {
334 sendFailure("Unknown WiFi async result type");
335 }
336 }
337
handleGnssAsyncResult(const chreAsyncResult * result)338 void Manager::handleGnssAsyncResult(const chreAsyncResult *result) {
339 if (isRequestTypeForLocation(result->requestType)) {
340 validateGnssAsyncResult(result, mGnssLocationAsyncRequest,
341 &mGnssLocationAsyncTimerHandle);
342 } else if (isRequestTypeForMeasurement(result->requestType)) {
343 validateGnssAsyncResult(result, mGnssMeasurementAsyncRequest,
344 &mGnssMeasurementAsyncTimerHandle);
345 } else {
346 sendFailure("Unknown GNSS async result type");
347 }
348 }
349
handleAudioDataEvent(const chreAudioDataEvent * event)350 void Manager::handleAudioDataEvent(const chreAudioDataEvent *event) {
351 uint64_t timestamp = event->timestamp;
352
353 checkTimestamp(timestamp, mPrevAudioEventTimestampMs);
354 mPrevAudioEventTimestampMs = timestamp;
355 }
356
handleAudioSamplingChangeEvent(const chreAudioSourceStatusEvent * event)357 void Manager::handleAudioSamplingChangeEvent(
358 const chreAudioSourceStatusEvent *event) {
359 LOGI("Received audio sampling change event - suspended: %d",
360 event->status.suspended);
361 }
362
validateGnssAsyncResult(const chreAsyncResult * result,Optional<AsyncRequest> & request,uint32_t * asyncTimerHandle)363 void Manager::validateGnssAsyncResult(const chreAsyncResult *result,
364 Optional<AsyncRequest> &request,
365 uint32_t *asyncTimerHandle) {
366 if (!request.has_value()) {
367 sendFailure("Received GNSS async result with no pending request");
368 } else if (!result->success) {
369 sendFailure("Async GNSS failure");
370 } else if (result->cookie != request->cookie) {
371 sendFailure("GNSS async cookie mismatch");
372 }
373
374 cancelTimer(asyncTimerHandle);
375 request.reset();
376 }
377
handleBleAdvertismentEvent(const chreBleAdvertisementEvent * event)378 void Manager::handleBleAdvertismentEvent(
379 const chreBleAdvertisementEvent *event) {
380 for (uint8_t i = 0; i < event->numReports; i++) {
381 uint64_t timestamp =
382 event->reports[i].timestamp / chre::kOneMillisecondInNanoseconds;
383
384 checkTimestamp(timestamp, mPrevBleAdTimestampMs);
385 mPrevBleAdTimestampMs = timestamp;
386 }
387 }
388
handleBleAsyncResult(const chreAsyncResult * result)389 void Manager::handleBleAsyncResult(const chreAsyncResult *result) {
390 const char *requestType =
391 result->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN ? "start"
392 : "stop";
393 if (!mBleScanAsyncRequest.has_value()) {
394 sendFailure("Received BLE async result with no pending request");
395 } else if (!result->success) {
396 LOGE("BLE %s scan failure: %" PRIu8, requestType, result->errorCode);
397 sendFailure("Async BLE failure");
398 } else if (result->cookie != mBleScanAsyncRequest->cookie) {
399 sendFailure("BLE async cookie mismatch");
400 } else {
401 LOGI("BLE %s scan success", requestType);
402 }
403 mBleScanAsyncRequest.reset();
404 }
405
checkTimestamp(uint64_t timestamp,uint64_t pastTimestamp)406 void Manager::checkTimestamp(uint64_t timestamp, uint64_t pastTimestamp) {
407 if (timestamp < pastTimestamp) {
408 sendFailure("Timestamp was too old");
409 } else if (timestamp == pastTimestamp) {
410 sendFailure("Timestamp was duplicate");
411 }
412 }
413
checkTimestampInterval(uint64_t timestamp,uint64_t pastTimestamp,uint64_t maxInterval)414 void Manager::checkTimestampInterval(uint64_t timestamp, uint64_t pastTimestamp,
415 uint64_t maxInterval) {
416 checkTimestamp(timestamp, pastTimestamp);
417 if (timestamp - pastTimestamp > maxInterval) {
418 LOGE("Timestamp is later than expected");
419 LOGI("Current timestamp %" PRIu64, timestamp);
420 LOGI("past timestamp %" PRIu64, pastTimestamp);
421 LOGI("Timestamp difference %" PRIu64, timestamp - pastTimestamp);
422 }
423 }
424
handleGnssLocationEvent(const chreGnssLocationEvent * event)425 void Manager::handleGnssLocationEvent(const chreGnssLocationEvent *event) {
426 LOGI("Received GNSS location event at %" PRIu64 " ms", event->timestamp);
427
428 checkTimestamp(event->timestamp, mPrevGnssLocationEventTimestampMs);
429 mPrevGnssLocationEventTimestampMs = event->timestamp;
430 }
431
handleGnssDataEvent(const chreGnssDataEvent * event)432 void Manager::handleGnssDataEvent(const chreGnssDataEvent *event) {
433 static uint32_t sPrevDiscontCount = 0;
434 LOGI("Received GNSS measurement event at %" PRIu64 " ns count %" PRIu32
435 " flags 0x%" PRIx16,
436 event->clock.time_ns, event->clock.hw_clock_discontinuity_count,
437 event->clock.flags);
438
439 if (sPrevDiscontCount == event->clock.hw_clock_discontinuity_count) {
440 checkTimestamp(event->clock.time_ns, mPrevGnssMeasurementEventTimestampNs);
441 }
442
443 sPrevDiscontCount = event->clock.hw_clock_discontinuity_count;
444 mPrevGnssMeasurementEventTimestampNs = event->clock.time_ns;
445 }
446
handleWifiScanEvent(const chreWifiScanEvent * event)447 void Manager::handleWifiScanEvent(const chreWifiScanEvent *event) {
448 LOGI("Received Wifi scan event of type %" PRIu8 " with %" PRIu8
449 " results at %" PRIu64 " ns",
450 event->scanType, event->resultCount, event->referenceTime);
451
452 if (event->eventIndex == 0) {
453 checkTimestamp(event->referenceTime, mPrevWifiScanEventTimestampNs);
454 mPrevWifiScanEventTimestampNs = event->referenceTime;
455 }
456
457 if (mWifiScanMonitorEnabled) {
458 chreSendMessageToHostEndpoint(
459 nullptr, 0,
460 chre_stress_test_MessageType_TEST_WIFI_SCAN_MONITOR_TRIGGERED,
461 mHostEndpoint.value(), nullptr /* freeCallback */);
462 }
463 }
464
handleAccelSensorDataEvent(const chreSensorThreeAxisData * eventData)465 void Manager::handleAccelSensorDataEvent(
466 const chreSensorThreeAxisData *eventData) {
467 const auto &header = eventData->header;
468 uint64_t timestamp = header.baseTimestamp;
469
470 // Note: The stress test sends streaming data request for accel, so only
471 // non-batched data are checked for timestamp. The allowed interval between
472 // data events is selected 1 ms higher than the sensor sampling interval to
473 // account for processing delays.
474 if (header.readingCount == 1) {
475 if (mPrevAccelEventTimestampNs != 0) {
476 checkTimestampInterval(timestamp, mPrevAccelEventTimestampNs,
477 mSensors[kAccelSensorIndex].samplingInterval +
478 kOneMillisecondInNanoseconds);
479 }
480 mPrevAccelEventTimestampNs = timestamp;
481 }
482 }
483
handleGyroSensorDataEvent(const chreSensorThreeAxisData * eventData)484 void Manager::handleGyroSensorDataEvent(
485 const chreSensorThreeAxisData *eventData) {
486 const auto &header = eventData->header;
487 uint64_t timestamp = header.baseTimestamp;
488
489 // Note: The stress test sends streaming data request for gyro, so only
490 // non-batched data are checked for timestamp. The interval is selected 1ms
491 // higher than the sensor sampling interval to account for processing delays.
492 if (header.readingCount == 1) {
493 if (mPrevGyroEventTimestampNs != 0) {
494 checkTimestampInterval(timestamp, mPrevGyroEventTimestampNs,
495 mSensors[kGyroSensorIndex].samplingInterval +
496 kOneMillisecondInNanoseconds);
497 }
498 mPrevGyroEventTimestampNs = timestamp;
499 }
500 }
501
handleInstantMotionSensorDataEvent(const chreSensorOccurrenceData * eventData)502 void Manager::handleInstantMotionSensorDataEvent(
503 const chreSensorOccurrenceData *eventData) {
504 const auto &header = eventData->header;
505 uint64_t timestamp = header.baseTimestamp;
506
507 mSensors[kInstantMotionSensorIndex].enabled = false;
508 checkTimestamp(timestamp, mPrevInstantMotionEventTimestampNs);
509 mPrevInstantMotionEventTimestampNs = timestamp;
510 }
511
handleSensorSamplingChangeEvent(const chreSensorSamplingStatusEvent * eventData)512 void Manager::handleSensorSamplingChangeEvent(
513 const chreSensorSamplingStatusEvent *eventData) {
514 LOGI("Sampling Change: handle %" PRIu32 ", status: interval %" PRIu64
515 " latency %" PRIu64 " enabled %d",
516 eventData->sensorHandle, eventData->status.interval,
517 eventData->status.latency, eventData->status.enabled);
518 if (eventData->sensorHandle == mSensors[kAccelSensorIndex].handle &&
519 eventData->status.interval !=
520 mSensors[kAccelSensorIndex].samplingInterval) {
521 mSensors[kAccelSensorIndex].samplingInterval = eventData->status.interval;
522 } else if (eventData->sensorHandle == mSensors[kGyroSensorIndex].handle &&
523 eventData->status.interval !=
524 mSensors[kGyroSensorIndex].samplingInterval) {
525 mSensors[kGyroSensorIndex].samplingInterval = eventData->status.interval;
526 }
527 }
528
handleCellInfoResult(const chreWwanCellInfoResult * event)529 void Manager::handleCellInfoResult(const chreWwanCellInfoResult *event) {
530 LOGI("Received %" PRIu8 " cell info results", event->cellInfoCount);
531
532 mWwanCellInfoAsyncRequest.reset();
533 if (event->errorCode != CHRE_ERROR_NONE) {
534 LOGE("Cell info request failed with error code %" PRIu8, event->errorCode);
535 sendFailure("Cell info request failed");
536 } else if (event->cellInfoCount > 0) {
537 uint64_t maxTimestamp = 0;
538 for (uint8_t i = 0; i < event->cellInfoCount; i++) {
539 maxTimestamp = MAX(maxTimestamp, event->cells[i].timeStamp);
540 checkTimestamp(event->cells[i].timeStamp,
541 mPrevWwanCellInfoEventTimestampNs);
542 }
543
544 mPrevWwanCellInfoEventTimestampNs = maxTimestamp;
545 }
546 }
547
handleWifiStartCommand(bool start)548 void Manager::handleWifiStartCommand(bool start) {
549 mWifiTestStarted = start;
550 if (start) {
551 requestDelayedWifiScan();
552 } else {
553 cancelTimer(&mWifiScanTimerHandle);
554 }
555 }
556
handleGnssLocationStartCommand(bool start)557 void Manager::handleGnssLocationStartCommand(bool start) {
558 constexpr uint64_t kTimerDelayNs = Seconds(60).toRawNanoseconds();
559
560 if (chreGnssGetCapabilities() & CHRE_GNSS_CAPABILITIES_LOCATION) {
561 mGnssLocationTestStarted = start;
562 makeGnssLocationRequest();
563
564 if (start) {
565 setTimer(kTimerDelayNs, false /* oneShot */, &mGnssLocationTimerHandle);
566 } else {
567 cancelTimer(&mGnssLocationTimerHandle);
568 }
569 } else {
570 LOGW("Platform has no location capability");
571 }
572 }
573
handleGnssMeasurementStartCommand(bool start)574 void Manager::handleGnssMeasurementStartCommand(bool start) {
575 constexpr uint64_t kTimerDelayNs = Seconds(60).toRawNanoseconds();
576
577 if (chreGnssGetCapabilities() & CHRE_GNSS_CAPABILITIES_MEASUREMENTS) {
578 mGnssMeasurementTestStarted = start;
579 makeGnssMeasurementRequest();
580
581 if (start) {
582 setTimer(kTimerDelayNs, false /* oneShot */,
583 &mGnssMeasurementTimerHandle);
584 } else {
585 cancelTimer(&mGnssMeasurementTimerHandle);
586 }
587 } else {
588 LOGW("Platform has no GNSS measurement capability");
589 }
590 }
591
handleWwanStartCommand(bool start)592 void Manager::handleWwanStartCommand(bool start) {
593 constexpr uint64_t kTimerDelayNs =
594 CHRE_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS;
595
596 if (chreWwanGetCapabilities() & CHRE_WWAN_GET_CELL_INFO) {
597 mWwanTestStarted = start;
598 makeWwanCellInfoRequest();
599
600 if (start) {
601 setTimer(kTimerDelayNs, false /* oneShot */, &mWwanTimerHandle);
602 } else {
603 cancelTimer(&mWwanTimerHandle);
604 }
605 } else {
606 LOGW("Platform has no WWAN cell info capability");
607 }
608 }
609
handleWifiScanMonitoringCommand(bool start)610 void Manager::handleWifiScanMonitoringCommand(bool start) {
611 if (chreWifiGetCapabilities() & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
612 const uint32_t kWifiScanMonitorEnabledCookie = 0x1234;
613 bool success = chreWifiConfigureScanMonitorAsync(
614 start, start ? &kWifiScanMonitorEnabledCookie : nullptr);
615 LOGI("Scan monitor enable %d request success ? %d", start, success);
616
617 if (!success) {
618 sendFailure("Scan monitor request failed");
619 } else {
620 setTimer(CHRE_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
621 true /* oneShot */, &mWifiScanMonitorAsyncTimerHandle);
622 }
623 } else {
624 LOGW("Platform has no WiFi scan monitoring capability");
625 }
626 }
627
handleSensorStartCommand(bool start)628 void Manager::handleSensorStartCommand(bool start) {
629 mSensorTestStarted = start;
630 bool sensorsFound = true;
631
632 for (size_t i = 0; i < ARRAY_SIZE(mSensors); i++) {
633 SensorState &sensor = mSensors[i];
634 bool isInitialized = chreSensorFindDefault(sensor.type, &sensor.handle);
635 if (!isInitialized) {
636 sensorsFound = false;
637 } else {
638 chreSensorInfo &info = sensor.info;
639 bool infoStatus = chreGetSensorInfo(sensor.handle, &info);
640 if (infoStatus) {
641 sensor.samplingInterval = info.minInterval;
642 LOGI("SensorInfo: %s, Type=%" PRIu8
643 " OnChange=%d OneShot=%d Passive=%d "
644 "minInterval=%" PRIu64 "nsec",
645 info.sensorName, info.sensorType, info.isOnChange, info.isOneShot,
646 info.supportsPassiveMode, info.minInterval);
647 } else {
648 LOGE("chreGetSensorInfo failed");
649 }
650 }
651 LOGI("Sensor %zu initialized: %s with handle %" PRIu32, i,
652 isInitialized ? "true" : "false", sensor.handle);
653 }
654
655 if (sensorsFound) {
656 if (start) {
657 makeSensorRequests();
658 } else {
659 stopSensorRequests();
660 cancelTimer(&mSensorTimerHandle);
661 }
662 } else {
663 LOGW("Platform has no sensor capability");
664 }
665 }
666
handleAudioStartCommand(bool start)667 void Manager::handleAudioStartCommand(bool start) {
668 mAudioTestStarted = start;
669 mAudioEnabled = true;
670
671 if (mAudioTestStarted) {
672 makeAudioRequest();
673 } else {
674 cancelTimer(&mAudioTimerHandle);
675 }
676 }
677
handleBleStartCommand(bool start)678 void Manager::handleBleStartCommand(bool start) {
679 if (chreBleGetCapabilities() & CHRE_BLE_CAPABILITIES_SCAN) {
680 mBleTestStarted = start;
681
682 if (start) {
683 makeBleScanRequest();
684 } else {
685 cancelTimer(&mBleScanTimerHandle);
686 }
687 } else {
688 sendFailure("Platform has no BLE capability");
689 }
690 }
691
setTimer(uint64_t delayNs,bool oneShot,uint32_t * timerHandle)692 void Manager::setTimer(uint64_t delayNs, bool oneShot, uint32_t *timerHandle) {
693 *timerHandle = chreTimerSet(delayNs, timerHandle, oneShot);
694 if (*timerHandle == CHRE_TIMER_INVALID) {
695 sendFailure("Failed to set timer");
696 }
697 }
698
cancelTimer(uint32_t * timerHandle)699 void Manager::cancelTimer(uint32_t *timerHandle) {
700 if (*timerHandle != CHRE_TIMER_INVALID) {
701 if (!chreTimerCancel(*timerHandle)) {
702 // We don't treat this as a test failure, because the CHRE API does not
703 // guarantee this method succeeds (e.g. if the timer is one-shot and just
704 // fired).
705 LOGW("Failed to cancel timer");
706 }
707 *timerHandle = CHRE_TIMER_INVALID;
708 }
709 }
710
makeSensorRequests()711 void Manager::makeSensorRequests() {
712 bool anySensorConfigured = false;
713 for (size_t i = 0; i < ARRAY_SIZE(mSensors); i++) {
714 SensorState &sensor = mSensors[i];
715 bool status = false;
716 if (!sensor.enabled) {
717 if (sensor.info.isOneShot) {
718 status = chreSensorConfigure(
719 sensor.handle, CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT,
720 CHRE_SENSOR_INTERVAL_DEFAULT, kSensorSamplingDelayNs);
721 } else {
722 status = chreSensorConfigure(
723 sensor.handle, CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS,
724 sensor.samplingInterval, kSensorSamplingDelayNs);
725 }
726 } else {
727 status = chreSensorConfigureModeOnly(sensor.handle,
728 CHRE_SENSOR_CONFIGURE_MODE_DONE);
729 if (i == kAccelSensorIndex) {
730 mPrevAccelEventTimestampNs = 0;
731 } else if (i == kGyroSensorIndex) {
732 mPrevGyroEventTimestampNs = 0;
733 }
734 }
735 if (status) {
736 sensor.enabled = !sensor.enabled;
737 }
738 LOGI("Configure [enable %d, status %d]: %s", sensor.enabled, status,
739 sensor.info.sensorName);
740 anySensorConfigured = anySensorConfigured || status;
741 }
742 if (anySensorConfigured) {
743 setTimer(kSensorRequestInterval.toRawNanoseconds(), true /* oneShot */,
744 &mSensorTimerHandle);
745 } else {
746 LOGW("Failed to make sensor request");
747 }
748 }
749
stopSensorRequests()750 void Manager::stopSensorRequests() {
751 for (size_t i = 0; i < ARRAY_SIZE(mSensors); i++) {
752 SensorState &sensor = mSensors[i];
753 if (sensor.enabled) {
754 if (!chreSensorConfigureModeOnly(sensor.handle,
755 CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
756 LOGE("Failed to disable sensor: %s", sensor.info.sensorName);
757 }
758 }
759 }
760 }
761
enableBleScan()762 bool Manager::enableBleScan() {
763 chreBleScanMode mode = mBleScanMode;
764 switch (mBleScanMode) {
765 case CHRE_BLE_SCAN_MODE_BACKGROUND:
766 mBleScanMode = CHRE_BLE_SCAN_MODE_FOREGROUND;
767 break;
768 case CHRE_BLE_SCAN_MODE_FOREGROUND:
769 mBleScanMode = CHRE_BLE_SCAN_MODE_AGGRESSIVE;
770 break;
771 case CHRE_BLE_SCAN_MODE_AGGRESSIVE:
772 mBleScanMode = CHRE_BLE_SCAN_MODE_BACKGROUND;
773 mShouldEnableBleScan = false;
774 break;
775 default:
776 sendFailure("Invalid scan mode");
777 break;
778 }
779 struct chreBleScanFilterV1_9 filter;
780 chreBleGenericFilter uuidFilters[kNumScanFilters];
781 createBleScanFilterForKnownBeaconsV1_9(filter, uuidFilters, kNumScanFilters);
782 return chreBleStartScanAsyncV1_9(mode, kBleBatchDurationMs, &filter,
783 &kBleScanCookie);
784 }
785
disableBleScan()786 bool Manager::disableBleScan() {
787 mShouldEnableBleScan = true;
788 return chreBleStopScanAsyncV1_9(&kBleScanCookie);
789 }
790
makeBleScanRequest()791 void Manager::makeBleScanRequest() {
792 bool success = false;
793 if (mShouldEnableBleScan) {
794 success = enableBleScan();
795 } else {
796 success = disableBleScan();
797 }
798
799 if (!success) {
800 LOGE("Failed to send BLE scan request");
801 } else {
802 mBleScanAsyncRequest = AsyncRequest(&kBleScanCookie);
803 setTimer(kBleRequestInterval.toRawNanoseconds(), true /* oneShot */,
804 &mBleScanTimerHandle);
805 }
806 }
807
makeGnssLocationRequest()808 void Manager::makeGnssLocationRequest() {
809 // The list of location intervals to iterate; wraps around.
810 static const uint32_t kMinIntervalMsList[] = {1000, 0};
811 static size_t sIntervalIndex = 0;
812
813 uint32_t minIntervalMs = 0;
814 if (mGnssLocationTestStarted) {
815 minIntervalMs = kMinIntervalMsList[sIntervalIndex];
816 sIntervalIndex = (sIntervalIndex + 1) % ARRAY_SIZE(kMinIntervalMsList);
817 } else {
818 sIntervalIndex = 0;
819 }
820
821 bool success = false;
822 if (minIntervalMs > 0) {
823 success = chreGnssLocationSessionStartAsync(
824 minIntervalMs, 0 /* minTimeToNextFixMs */, &kGnssLocationCookie);
825 } else {
826 success = chreGnssLocationSessionStopAsync(&kGnssLocationCookie);
827 }
828
829 LOGI("Configure GNSS location interval %" PRIu32 " ms success ? %d",
830 minIntervalMs, success);
831
832 if (!success) {
833 sendFailure("Failed to make location request");
834 } else {
835 mGnssLocationAsyncRequest = AsyncRequest(&kGnssLocationCookie);
836 setTimer(CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
837 true /* oneShot */, &mGnssLocationAsyncTimerHandle);
838 }
839 }
840
makeGnssMeasurementRequest()841 void Manager::makeGnssMeasurementRequest() {
842 // The list of measurement intervals to iterate; wraps around.
843 static const uint32_t kMinIntervalMsList[] = {1000, 0};
844 static size_t sIntervalIndex = 0;
845
846 uint32_t minIntervalMs = 0;
847 if (mGnssMeasurementTestStarted) {
848 minIntervalMs = kMinIntervalMsList[sIntervalIndex];
849 sIntervalIndex = (sIntervalIndex + 1) % ARRAY_SIZE(kMinIntervalMsList);
850 } else {
851 sIntervalIndex = 0;
852 }
853
854 bool success = false;
855 if (minIntervalMs > 0) {
856 success = chreGnssMeasurementSessionStartAsync(minIntervalMs,
857 &kGnssMeasurementCookie);
858 } else {
859 success = chreGnssMeasurementSessionStopAsync(&kGnssMeasurementCookie);
860 // Reset the previous timestamp, since the GNSS internal clock may reset.
861 mPrevGnssMeasurementEventTimestampNs = 0;
862 }
863
864 LOGI("Configure GNSS measurement interval %" PRIu32 " ms success ? %d",
865 minIntervalMs, success);
866
867 if (!success) {
868 sendFailure("Failed to make measurement request");
869 } else {
870 mGnssMeasurementAsyncRequest = AsyncRequest(&kGnssMeasurementCookie);
871 setTimer(CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
872 true /* oneShot */, &mGnssMeasurementAsyncTimerHandle);
873 }
874 }
875
requestDelayedWifiScan()876 void Manager::requestDelayedWifiScan() {
877 if (mWifiTestStarted) {
878 if (chreWifiGetCapabilities() & CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN) {
879 setTimer(kWifiScanInterval.toRawNanoseconds(), true /* oneShot */,
880 &mWifiScanTimerHandle);
881 } else {
882 LOGW("Platform has no on-demand scan capability");
883 }
884 }
885 }
886
makeWwanCellInfoRequest()887 void Manager::makeWwanCellInfoRequest() {
888 if (mWwanTestStarted) {
889 if (mWwanCellInfoAsyncRequest.has_value()) {
890 if (chreGetTime() > mWwanCellInfoAsyncRequest->requestTimeNs +
891 CHRE_ASYNC_RESULT_TIMEOUT_NS) {
892 sendFailure("Prev cell info request did not complete in time");
893 }
894 } else {
895 bool success = chreWwanGetCellInfoAsync(&kWwanCellInfoCookie);
896
897 LOGI("Cell info request success ? %d", success);
898
899 if (!success) {
900 sendFailure("Failed to make cell info request");
901 } else {
902 mWwanCellInfoAsyncRequest = AsyncRequest(&kWwanCellInfoCookie);
903 }
904 }
905 }
906 }
907
makeAudioRequest()908 void Manager::makeAudioRequest() {
909 bool success = false;
910 struct chreAudioSource source;
911 if (mAudioEnabled) {
912 for (uint32_t i = 0; chreAudioGetSource(i, &source); i++) {
913 if (chreAudioConfigureSource(i, true, source.minBufferDuration,
914 source.minBufferDuration)) {
915 LOGI("Successfully enabled audio for source %" PRIu32, i);
916 success = true;
917 } else {
918 LOGE("Failed to enable audio");
919 }
920 }
921 } else {
922 for (uint32_t i = 0; chreAudioGetSource(i, &source); i++) {
923 if (chreAudioConfigureSource(i, false, 0, 0)) {
924 LOGI("Successfully disabled audio for source %" PRIu32, i);
925 success = true;
926 } else {
927 LOGE("Failed to disable audio");
928 }
929 }
930 }
931
932 if (success) {
933 mAudioEnabled = !mAudioEnabled;
934 setTimer(kAudioRequestInterval.toRawNanoseconds(), true /* oneShot */,
935 &mAudioTimerHandle);
936 } else {
937 sendFailure("Failed to make audio request");
938 }
939 }
940
sendFailure(const char * errorMessage)941 void Manager::sendFailure(const char *errorMessage) {
942 test_shared::sendTestResultWithMsgToHost(
943 mHostEndpoint.value(),
944 chre_stress_test_MessageType_TEST_RESULT /* messageType */,
945 false /* success */, errorMessage, false /* abortOnFailure */);
946 }
947
sendCapabilitiesMessage()948 void Manager::sendCapabilitiesMessage() {
949 if (!mHostEndpoint.has_value()) {
950 LOGE("mHostEndpoint is not initialized");
951 return;
952 }
953
954 chre_stress_test_Capabilities capabilities =
955 chre_stress_test_Capabilities_init_default;
956 capabilities.wifi = chreWifiGetCapabilities();
957
958 size_t size;
959 if (!pb_get_encoded_size(&size, chre_stress_test_Capabilities_fields,
960 &capabilities)) {
961 LOGE("Failed to get message size");
962 return;
963 }
964
965 pb_byte_t *bytes = static_cast<pb_byte_t *>(chreHeapAlloc(size));
966 if (size > 0 && bytes == nullptr) {
967 LOG_OOM();
968 } else {
969 pb_ostream_t stream = pb_ostream_from_buffer(bytes, size);
970 if (!pb_encode(&stream, chre_stress_test_Capabilities_fields,
971 &capabilities)) {
972 LOGE("Failed to encode capabilities error %s", PB_GET_ERROR(&stream));
973 chreHeapFree(bytes);
974 } else {
975 chreSendMessageToHostEndpoint(
976 bytes, size, chre_stress_test_MessageType_CAPABILITIES,
977 mHostEndpoint.value(), heapFreeMessageCallback);
978 }
979 }
980 }
981
982 } // namespace stress_test
983
984 } // namespace chre
985