• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, &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