• 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/nanoapp/callbacks.h"
24 #include "chre/util/nanoapp/log.h"
25 #include "chre_stress_test.nanopb.h"
26 #include "send_message.h"
27 
28 #define LOG_TAG "[ChreStressTest]"
29 
30 namespace chre {
31 
32 namespace stress_test {
33 
34 namespace {
35 
36 //! Additional duration to handle request timeout over the specified
37 //! CHRE API timeout (to account for processing delay).
38 #define TIMEOUT_BUFFER_DELAY_NS (1 * CHRE_NSEC_PER_SEC)
39 
40 constexpr chre::Nanoseconds kWifiScanInterval = chre::Seconds(5);
41 
isRequestTypeForLocation(uint8_t requestType)42 bool isRequestTypeForLocation(uint8_t requestType) {
43   return (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START) ||
44          (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP);
45 }
46 
isRequestTypeForMeasurement(uint8_t requestType)47 bool isRequestTypeForMeasurement(uint8_t requestType) {
48   return (requestType == CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_START) ||
49          (requestType == CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP);
50 }
51 
52 }  // anonymous namespace
53 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)54 void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
55                           const void *eventData) {
56   if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
57     handleMessageFromHost(
58         senderInstanceId,
59         static_cast<const chreMessageFromHostData *>(eventData));
60   } else if (senderInstanceId == CHRE_INSTANCE_ID) {
61     handleDataFromChre(eventType, eventData);
62   } else {
63     LOGW("Got unknown event type from senderInstanceId %" PRIu32
64          " and with eventType %" PRIu16,
65          senderInstanceId, eventType);
66   }
67 }
68 
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)69 void Manager::handleMessageFromHost(uint32_t senderInstanceId,
70                                     const chreMessageFromHostData *hostData) {
71   bool success = false;
72   uint32_t messageType = hostData->messageType;
73   if (senderInstanceId != CHRE_INSTANCE_ID) {
74     LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
75   } else if (messageType == chre_stress_test_MessageType_TEST_HOST_RESTARTED) {
76     // Do nothing and only update the host endpoint
77     mHostEndpoint = hostData->hostEndpoint;
78     success = true;
79   } else if (messageType == chre_stress_test_MessageType_GET_CAPABILITIES) {
80     sendCapabilitiesMessage();
81     success = true;
82   } else if (messageType != chre_stress_test_MessageType_TEST_COMMAND) {
83     LOGE("Invalid message type %" PRIu32, messageType);
84   } else if (mHostEndpoint.has_value() &&
85              hostData->hostEndpoint != mHostEndpoint.value()) {
86     LOGE("Invalid host endpoint %" PRIu16 " expected %" PRIu16,
87          hostData->hostEndpoint, mHostEndpoint.value());
88   } else {
89     pb_istream_t istream = pb_istream_from_buffer(
90         static_cast<const pb_byte_t *>(hostData->message),
91         hostData->messageSize);
92     chre_stress_test_TestCommand testCommand =
93         chre_stress_test_TestCommand_init_default;
94 
95     if (!pb_decode(&istream, chre_stress_test_TestCommand_fields,
96                    &testCommand)) {
97       LOGE("Failed to decode start command error %s", PB_GET_ERROR(&istream));
98     } else {
99       LOGI("Got message from host: feature %d start %d", testCommand.feature,
100            testCommand.start);
101 
102       success = true;
103       switch (testCommand.feature) {
104         case chre_stress_test_TestCommand_Feature_WIFI_ON_DEMAND_SCAN: {
105           handleWifiStartCommand(testCommand.start);
106           break;
107         }
108         case chre_stress_test_TestCommand_Feature_GNSS_LOCATION: {
109           handleGnssLocationStartCommand(testCommand.start);
110           break;
111         }
112         case chre_stress_test_TestCommand_Feature_GNSS_MEASUREMENT: {
113           handleGnssMeasurementStartCommand(testCommand.start);
114           break;
115         }
116         case chre_stress_test_TestCommand_Feature_WWAN: {
117           handleWwanStartCommand(testCommand.start);
118           break;
119         }
120         case chre_stress_test_TestCommand_Feature_WIFI_SCAN_MONITOR: {
121           handleWifiScanMonitoringCommand(testCommand.start);
122           break;
123         }
124         default: {
125           LOGE("Unknown feature %d", testCommand.feature);
126           success = false;
127           break;
128         }
129       }
130     }
131 
132     mHostEndpoint = hostData->hostEndpoint;
133   }
134 
135   if (!success) {
136     test_shared::sendTestResultWithMsgToHost(
137         hostData->hostEndpoint,
138         chre_stress_test_MessageType_TEST_RESULT /* messageType */, success,
139         nullptr /* errMessage */);
140   }
141 }
142 
handleDataFromChre(uint16_t eventType,const void * eventData)143 void Manager::handleDataFromChre(uint16_t eventType, const void *eventData) {
144   switch (eventType) {
145     case CHRE_EVENT_TIMER:
146       handleTimerEvent(static_cast<const uint32_t *>(eventData));
147       break;
148 
149     case CHRE_EVENT_WIFI_ASYNC_RESULT:
150       handleWifiAsyncResult(static_cast<const chreAsyncResult *>(eventData));
151       break;
152 
153     case CHRE_EVENT_WIFI_SCAN_RESULT:
154       handleWifiScanEvent(static_cast<const chreWifiScanEvent *>(eventData));
155       break;
156 
157     case CHRE_EVENT_GNSS_ASYNC_RESULT:
158       handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData));
159       break;
160 
161     case CHRE_EVENT_GNSS_LOCATION:
162       handleGnssLocationEvent(
163           static_cast<const chreGnssLocationEvent *>(eventData));
164       break;
165 
166     case CHRE_EVENT_GNSS_DATA:
167       handleGnssDataEvent(static_cast<const chreGnssDataEvent *>(eventData));
168       break;
169 
170     case CHRE_EVENT_WWAN_CELL_INFO_RESULT:
171       handleCellInfoResult(
172           static_cast<const chreWwanCellInfoResult *>(eventData));
173       break;
174 
175     default:
176       LOGW("Unknown event type %" PRIu16, eventType);
177       break;
178   }
179 }
180 
handleTimerEvent(const uint32_t * handle)181 void Manager::handleTimerEvent(const uint32_t *handle) {
182   if (*handle == mWifiScanTimerHandle) {
183     handleDelayedWifiTimer();
184   } else if (*handle == mWifiScanAsyncTimerHandle) {
185     sendFailure("WiFi scan request timed out");
186   } else if (*handle == mGnssLocationTimerHandle) {
187     makeGnssLocationRequest();
188   } else if (*handle == mGnssMeasurementTimerHandle) {
189     makeGnssMeasurementRequest();
190   } else if (*handle == mGnssLocationAsyncTimerHandle &&
191              mGnssLocationAsyncRequest.has_value()) {
192     sendFailure("GNSS location async result timed out");
193   } else if (*handle == mGnssMeasurementAsyncTimerHandle &&
194              mGnssMeasurementAsyncRequest.has_value()) {
195     sendFailure("GNSS measurement async result timed out");
196   } else if (*handle == mWwanTimerHandle) {
197     makeWwanCellInfoRequest();
198   } else if (*handle == mWifiScanMonitorAsyncTimerHandle) {
199     sendFailure("WiFi scan monitor request timed out");
200   } else {
201     sendFailure("Unknown timer handle");
202   }
203 }
204 
handleDelayedWifiTimer()205 void Manager::handleDelayedWifiTimer() {
206   // NOTE: We set the maxScanAgeMs to something smaller than the WiFi
207   // scan periodicity to ensure new scans are generated.
208   static const struct chreWifiScanParams params = {
209       /*.scanType=*/CHRE_WIFI_SCAN_TYPE_NO_PREFERENCE,
210       /*.maxScanAgeMs=*/2000,  // 2 seconds
211       /*.frequencyListLen=*/0,
212       /*.frequencyList=*/NULL,
213       /*.ssidListLen=*/0,
214       /*.ssidList=*/NULL,
215       /*.radioChainPref=*/CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT,
216       /*.channelSet=*/CHRE_WIFI_CHANNEL_SET_NON_DFS};
217 
218   bool success = chreWifiRequestScanAsync(&params, &kOnDemandWifiScanCookie);
219   LOGI("Requested on demand wifi success ? %d", success);
220   if (!success) {
221     sendFailure("Failed to make WiFi scan request");
222   } else {
223     mWifiScanAsyncRequest = AsyncRequest(&kOnDemandWifiScanCookie);
224     setTimer(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
225              true /* oneShot */, &mWifiScanAsyncTimerHandle);
226   }
227 }
228 
handleWifiAsyncResult(const chreAsyncResult * result)229 void Manager::handleWifiAsyncResult(const chreAsyncResult *result) {
230   if (result->requestType == CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN) {
231     if (result->success) {
232       LOGI("On-demand scan success");
233     } else {
234       LOGW("On-demand scan failed: code %" PRIu8, result->errorCode);
235     }
236 
237     if (!mWifiScanAsyncRequest.has_value()) {
238       sendFailure("Received WiFi async result with no pending request");
239     } else if (result->cookie != mWifiScanAsyncRequest->cookie) {
240       sendFailure("On-demand scan cookie mismatch");
241     }
242 
243     cancelTimer(&mWifiScanAsyncTimerHandle);
244     mWifiScanAsyncRequest.reset();
245     requestDelayedWifiScan();
246   } else if (result->requestType ==
247              CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR) {
248     if (!result->success) {
249       LOGE("Scan monitor async failure: code %" PRIu8, result->errorCode);
250       sendFailure("Scan monitor async failed");
251     }
252 
253     cancelTimer(&mWifiScanMonitorAsyncTimerHandle);
254     mWifiScanMonitorEnabled = (result->cookie != nullptr);
255   } else {
256     sendFailure("Unknown WiFi async result type");
257   }
258 }
259 
handleGnssAsyncResult(const chreAsyncResult * result)260 void Manager::handleGnssAsyncResult(const chreAsyncResult *result) {
261   if (isRequestTypeForLocation(result->requestType)) {
262     validateGnssAsyncResult(result, mGnssLocationAsyncRequest,
263                             &mGnssLocationAsyncTimerHandle);
264   } else if (isRequestTypeForMeasurement(result->requestType)) {
265     validateGnssAsyncResult(result, mGnssMeasurementAsyncRequest,
266                             &mGnssMeasurementAsyncTimerHandle);
267   } else {
268     sendFailure("Unknown GNSS async result type");
269   }
270 }
271 
validateGnssAsyncResult(const chreAsyncResult * result,Optional<AsyncRequest> & request,uint32_t * asyncTimerHandle)272 void Manager::validateGnssAsyncResult(const chreAsyncResult *result,
273                                       Optional<AsyncRequest> &request,
274                                       uint32_t *asyncTimerHandle) {
275   if (!request.has_value()) {
276     sendFailure("Received GNSS async result with no pending request");
277   } else if (!result->success) {
278     sendFailure("Async GNSS failure");
279   } else if (result->cookie != request->cookie) {
280     sendFailure("GNSS async cookie mismatch");
281   }
282 
283   cancelTimer(asyncTimerHandle);
284   request.reset();
285 }
286 
checkTimestamp(uint64_t timestamp,uint64_t pastTimestamp)287 void Manager::checkTimestamp(uint64_t timestamp, uint64_t pastTimestamp) {
288   if (timestamp < pastTimestamp) {
289     sendFailure("Timestamp was too old");
290   } else if (timestamp == pastTimestamp) {
291     sendFailure("Timestamp was duplicate");
292   }
293 }
294 
handleGnssLocationEvent(const chreGnssLocationEvent * event)295 void Manager::handleGnssLocationEvent(const chreGnssLocationEvent *event) {
296   LOGI("Received GNSS location event at %" PRIu64 " ms", event->timestamp);
297 
298   checkTimestamp(event->timestamp, mPrevGnssLocationEventTimestampMs);
299   mPrevGnssLocationEventTimestampMs = event->timestamp;
300 }
301 
handleGnssDataEvent(const chreGnssDataEvent * event)302 void Manager::handleGnssDataEvent(const chreGnssDataEvent *event) {
303   static uint32_t sPrevDiscontCount = 0;
304   LOGI("Received GNSS measurement event at %" PRIu64 " ns count %" PRIu32
305        " flags 0x%" PRIx16,
306        event->clock.time_ns, event->clock.hw_clock_discontinuity_count,
307        event->clock.flags);
308 
309   if (sPrevDiscontCount == event->clock.hw_clock_discontinuity_count) {
310     checkTimestamp(event->clock.time_ns, mPrevGnssMeasurementEventTimestampNs);
311   }
312 
313   sPrevDiscontCount = event->clock.hw_clock_discontinuity_count;
314   mPrevGnssMeasurementEventTimestampNs = event->clock.time_ns;
315 }
316 
handleWifiScanEvent(const chreWifiScanEvent * event)317 void Manager::handleWifiScanEvent(const chreWifiScanEvent *event) {
318   LOGI("Received Wifi scan event of type %" PRIu8 " with %" PRIu8
319        " results at %" PRIu64 " ns",
320        event->scanType, event->resultCount, event->referenceTime);
321 
322   if (event->eventIndex == 0) {
323     checkTimestamp(event->referenceTime, mPrevWifiScanEventTimestampNs);
324     mPrevWifiScanEventTimestampNs = event->referenceTime;
325   }
326 
327   if (mWifiScanMonitorEnabled) {
328     chreSendMessageToHostEndpoint(
329         nullptr, 0,
330         chre_stress_test_MessageType_TEST_WIFI_SCAN_MONITOR_TRIGGERED,
331         mHostEndpoint.value(), nullptr /* freeCallback */);
332   }
333 }
334 
handleCellInfoResult(const chreWwanCellInfoResult * event)335 void Manager::handleCellInfoResult(const chreWwanCellInfoResult *event) {
336   LOGI("Received %" PRIu8 " cell info results", event->cellInfoCount);
337 
338   mWwanCellInfoAsyncRequest.reset();
339   if (event->errorCode != CHRE_ERROR_NONE) {
340     LOGE("Cell info request failed with error code %" PRIu8, event->errorCode);
341     sendFailure("Cell info request failed");
342   } else if (event->cellInfoCount > 0) {
343     uint64_t maxTimestamp = 0;
344     for (uint8_t i = 0; i < event->cellInfoCount; i++) {
345       maxTimestamp = MAX(maxTimestamp, event->cells[i].timeStamp);
346       checkTimestamp(event->cells[i].timeStamp,
347                      mPrevWwanCellInfoEventTimestampNs);
348     }
349 
350     mPrevWwanCellInfoEventTimestampNs = maxTimestamp;
351   }
352 }
353 
handleWifiStartCommand(bool start)354 void Manager::handleWifiStartCommand(bool start) {
355   mWifiTestStarted = start;
356   if (start) {
357     requestDelayedWifiScan();
358   } else {
359     cancelTimer(&mWifiScanTimerHandle);
360   }
361 }
362 
handleGnssLocationStartCommand(bool start)363 void Manager::handleGnssLocationStartCommand(bool start) {
364   constexpr uint64_t kTimerDelayNs = Seconds(60).toRawNanoseconds();
365 
366   if (chreGnssGetCapabilities() & CHRE_GNSS_CAPABILITIES_LOCATION) {
367     mGnssLocationTestStarted = start;
368     makeGnssLocationRequest();
369 
370     if (start) {
371       setTimer(kTimerDelayNs, false /* oneShot */, &mGnssLocationTimerHandle);
372     } else {
373       cancelTimer(&mGnssLocationTimerHandle);
374     }
375   } else {
376     sendFailure("Platform has no location capability");
377   }
378 }
379 
handleGnssMeasurementStartCommand(bool start)380 void Manager::handleGnssMeasurementStartCommand(bool start) {
381   constexpr uint64_t kTimerDelayNs = Seconds(60).toRawNanoseconds();
382 
383   if (chreGnssGetCapabilities() & CHRE_GNSS_CAPABILITIES_MEASUREMENTS) {
384     mGnssMeasurementTestStarted = start;
385     makeGnssMeasurementRequest();
386 
387     if (start) {
388       setTimer(kTimerDelayNs, false /* oneShot */,
389                &mGnssMeasurementTimerHandle);
390     } else {
391       cancelTimer(&mGnssMeasurementTimerHandle);
392     }
393   } else {
394     sendFailure("Platform has no GNSS measurement capability");
395   }
396 }
397 
handleWwanStartCommand(bool start)398 void Manager::handleWwanStartCommand(bool start) {
399   constexpr uint64_t kTimerDelayNs =
400       CHRE_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS;
401 
402   if (chreWwanGetCapabilities() & CHRE_WWAN_GET_CELL_INFO) {
403     mWwanTestStarted = start;
404     makeWwanCellInfoRequest();
405 
406     if (start) {
407       setTimer(kTimerDelayNs, false /* oneShot */, &mWwanTimerHandle);
408     } else {
409       cancelTimer(&mWwanTimerHandle);
410     }
411   } else {
412     sendFailure("Platform has no WWAN cell info capability");
413   }
414 }
415 
handleWifiScanMonitoringCommand(bool start)416 void Manager::handleWifiScanMonitoringCommand(bool start) {
417   if (chreWifiGetCapabilities() & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
418     const uint32_t kWifiScanMonitorEnabledCookie = 0x1234;
419     bool success = chreWifiConfigureScanMonitorAsync(
420         start, start ? &kWifiScanMonitorEnabledCookie : nullptr);
421     LOGI("Scan monitor enable %d request success ? %d", start, success);
422 
423     if (!success) {
424       sendFailure("Scan monitor request failed");
425     } else {
426       setTimer(CHRE_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
427                true /* oneShot */, &mWifiScanMonitorAsyncTimerHandle);
428     }
429   } else {
430     sendFailure("Platform has no WiFi scan monitoring capability");
431   }
432 }
433 
setTimer(uint64_t delayNs,bool oneShot,uint32_t * timerHandle)434 void Manager::setTimer(uint64_t delayNs, bool oneShot, uint32_t *timerHandle) {
435   *timerHandle = chreTimerSet(delayNs, timerHandle, oneShot);
436   if (*timerHandle == CHRE_TIMER_INVALID) {
437     sendFailure("Failed to set timer");
438   }
439 }
440 
cancelTimer(uint32_t * timerHandle)441 void Manager::cancelTimer(uint32_t *timerHandle) {
442   if (*timerHandle != CHRE_TIMER_INVALID) {
443     if (!chreTimerCancel(*timerHandle)) {
444       // We don't treat this as a test failure, because the CHRE API does not
445       // guarantee this method succeeds (e.g. if the timer is one-shot and just
446       // fired).
447       LOGW("Failed to cancel timer");
448     }
449     *timerHandle = CHRE_TIMER_INVALID;
450   }
451 }
452 
makeGnssLocationRequest()453 void Manager::makeGnssLocationRequest() {
454   // The list of location intervals to iterate; wraps around.
455   static const uint32_t kMinIntervalMsList[] = {1000, 0};
456   static size_t sIntervalIndex = 0;
457 
458   uint32_t minIntervalMs = 0;
459   if (mGnssLocationTestStarted) {
460     minIntervalMs = kMinIntervalMsList[sIntervalIndex];
461     sIntervalIndex = (sIntervalIndex + 1) % ARRAY_SIZE(kMinIntervalMsList);
462   } else {
463     sIntervalIndex = 0;
464   }
465 
466   bool success = false;
467   if (minIntervalMs > 0) {
468     success = chreGnssLocationSessionStartAsync(
469         minIntervalMs, 0 /* minTimeToNextFixMs */, &kGnssLocationCookie);
470   } else {
471     success = chreGnssLocationSessionStopAsync(&kGnssLocationCookie);
472   }
473 
474   LOGI("Configure GNSS location interval %" PRIu32 " ms success ? %d",
475        minIntervalMs, success);
476 
477   if (!success) {
478     sendFailure("Failed to make location request");
479   } else {
480     mGnssLocationAsyncRequest = AsyncRequest(&kGnssLocationCookie);
481     setTimer(CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
482              true /* oneShot */, &mGnssLocationAsyncTimerHandle);
483   }
484 }
485 
makeGnssMeasurementRequest()486 void Manager::makeGnssMeasurementRequest() {
487   // The list of measurement intervals to iterate; wraps around.
488   static const uint32_t kMinIntervalMsList[] = {1000, 0};
489   static size_t sIntervalIndex = 0;
490 
491   uint32_t minIntervalMs = 0;
492   if (mGnssMeasurementTestStarted) {
493     minIntervalMs = kMinIntervalMsList[sIntervalIndex];
494     sIntervalIndex = (sIntervalIndex + 1) % ARRAY_SIZE(kMinIntervalMsList);
495   } else {
496     sIntervalIndex = 0;
497   }
498 
499   bool success = false;
500   if (minIntervalMs > 0) {
501     success = chreGnssMeasurementSessionStartAsync(minIntervalMs,
502                                                    &kGnssMeasurementCookie);
503   } else {
504     success = chreGnssMeasurementSessionStopAsync(&kGnssMeasurementCookie);
505     // Reset the previous timestamp, since the GNSS internal clock may reset.
506     mPrevGnssMeasurementEventTimestampNs = 0;
507   }
508 
509   LOGI("Configure GNSS measurement interval %" PRIu32 " ms success ? %d",
510        minIntervalMs, success);
511 
512   if (!success) {
513     sendFailure("Failed to make measurement request");
514   } else {
515     mGnssMeasurementAsyncRequest = AsyncRequest(&kGnssMeasurementCookie);
516     setTimer(CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS + TIMEOUT_BUFFER_DELAY_NS,
517              true /* oneShot */, &mGnssMeasurementAsyncTimerHandle);
518   }
519 }
520 
requestDelayedWifiScan()521 void Manager::requestDelayedWifiScan() {
522   if (mWifiTestStarted) {
523     if (chreWifiGetCapabilities() & CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN) {
524       setTimer(kWifiScanInterval.toRawNanoseconds(), true /* oneShot */,
525                &mWifiScanTimerHandle);
526     } else {
527       sendFailure("Platform has no on-demand scan capability");
528     }
529   }
530 }
531 
makeWwanCellInfoRequest()532 void Manager::makeWwanCellInfoRequest() {
533   if (mWwanTestStarted) {
534     if (mWwanCellInfoAsyncRequest.has_value()) {
535       if (chreGetTime() > mWwanCellInfoAsyncRequest->requestTimeNs +
536                               CHRE_ASYNC_RESULT_TIMEOUT_NS) {
537         sendFailure("Prev cell info request did not complete in time");
538       }
539     } else {
540       bool success = chreWwanGetCellInfoAsync(&kWwanCellInfoCookie);
541 
542       LOGI("Cell info request success ? %d", success);
543 
544       if (!success) {
545         sendFailure("Failed to make cell info request");
546       } else {
547         mWwanCellInfoAsyncRequest = AsyncRequest(&kWwanCellInfoCookie);
548       }
549     }
550   }
551 }
552 
sendFailure(const char * errorMessage)553 void Manager::sendFailure(const char *errorMessage) {
554   test_shared::sendTestResultWithMsgToHost(
555       mHostEndpoint.value(),
556       chre_stress_test_MessageType_TEST_RESULT /* messageType */,
557       false /* success */, errorMessage, false /* abortOnFailure */);
558 }
559 
sendCapabilitiesMessage()560 void Manager::sendCapabilitiesMessage() {
561   if (!mHostEndpoint.has_value()) {
562     LOGE("mHostEndpoint is not initialized");
563     return;
564   }
565 
566   chre_stress_test_Capabilities capabilities =
567       chre_stress_test_Capabilities_init_default;
568   capabilities.wifi = chreWifiGetCapabilities();
569 
570   size_t size;
571   if (!pb_get_encoded_size(&size, chre_stress_test_Capabilities_fields,
572                            &capabilities)) {
573     LOGE("Failed to get message size");
574     return;
575   }
576 
577   pb_byte_t *bytes = static_cast<pb_byte_t *>(chreHeapAlloc(size));
578   if (size > 0 && bytes == nullptr) {
579     LOG_OOM();
580   } else {
581     pb_ostream_t stream = pb_ostream_from_buffer(bytes, size);
582     if (!pb_encode(&stream, chre_stress_test_Capabilities_fields,
583                    &capabilities)) {
584       LOGE("Failed to encode capabilities error %s", PB_GET_ERROR(&stream));
585       chreHeapFree(bytes);
586     } else {
587       chreSendMessageToHostEndpoint(
588           bytes, size, chre_stress_test_MessageType_CAPABILITIES,
589           mHostEndpoint.value(), heapFreeMessageCallback);
590     }
591   }
592 }
593 
594 }  // namespace stress_test
595 
596 }  // namespace chre
597