• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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_settings_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/ble.h"
24 #include "chre/util/nanoapp/callbacks.h"
25 #include "chre/util/nanoapp/log.h"
26 #include "chre/util/time.h"
27 #include "chre_settings_test.nanopb.h"
28 #include "send_message.h"
29 
30 #define LOG_TAG "[ChreSettingsTest]"
31 
32 using chre::createBleScanFilterForKnownBeacons;
33 using chre::ble_constants::kNumScanFilters;
34 
35 namespace chre {
36 
37 namespace settings_test {
38 
39 namespace {
40 
41 constexpr uint32_t kWifiScanningCookie = 0x1234;
42 constexpr uint32_t kWifiRttCookie = 0x2345;
43 constexpr uint32_t kGnssLocationCookie = 0x3456;
44 constexpr uint32_t kGnssMeasurementCookie = 0x4567;
45 constexpr uint32_t kWwanCellInfoCookie = 0x5678;
46 
47 // Flag to verify if an audio data event was received after a valid sampling
48 // change event (i.e., we only got the data event after a source-enabled-and-
49 // not-suspended event).
50 bool gGotSourceEnabledEvent = false;
51 
52 uint32_t gAudioDataTimerHandle = CHRE_TIMER_INVALID;
53 constexpr uint32_t kAudioDataTimerCookie = 0xc001cafe;
54 uint32_t gAudioStatusTimerHandle = CHRE_TIMER_INVALID;
55 constexpr uint32_t kAudioStatusTimerCookie = 0xb01dcafe;
56 
getFeature(const chre_settings_test_TestCommand & command,Manager::Feature * feature)57 bool getFeature(const chre_settings_test_TestCommand &command,
58                 Manager::Feature *feature) {
59   bool success = true;
60   switch (command.feature) {
61     case chre_settings_test_TestCommand_Feature_WIFI_SCANNING:
62       *feature = Manager::Feature::WIFI_SCANNING;
63       break;
64     case chre_settings_test_TestCommand_Feature_WIFI_RTT:
65       *feature = Manager::Feature::WIFI_RTT;
66       break;
67     case chre_settings_test_TestCommand_Feature_GNSS_LOCATION:
68       *feature = Manager::Feature::GNSS_LOCATION;
69       break;
70     case chre_settings_test_TestCommand_Feature_GNSS_MEASUREMENT:
71       *feature = Manager::Feature::GNSS_MEASUREMENT;
72       break;
73     case chre_settings_test_TestCommand_Feature_WWAN_CELL_INFO:
74       *feature = Manager::Feature::WWAN_CELL_INFO;
75       break;
76     case chre_settings_test_TestCommand_Feature_AUDIO:
77       *feature = Manager::Feature::AUDIO;
78       break;
79     case chre_settings_test_TestCommand_Feature_BLE_SCANNING:
80       *feature = Manager::Feature::BLE_SCANNING;
81       break;
82     default:
83       LOGE("Unknown feature %d", command.feature);
84       success = false;
85   }
86 
87   return success;
88 }
89 
getFeatureState(const chre_settings_test_TestCommand & command,Manager::FeatureState * state)90 bool getFeatureState(const chre_settings_test_TestCommand &command,
91                      Manager::FeatureState *state) {
92   bool success = true;
93   switch (command.state) {
94     case chre_settings_test_TestCommand_State_ENABLED:
95       *state = Manager::FeatureState::ENABLED;
96       break;
97     case chre_settings_test_TestCommand_State_DISABLED:
98       *state = Manager::FeatureState::DISABLED;
99       break;
100     default:
101       LOGE("Unknown feature state %d", command.state);
102       success = false;
103   }
104 
105   return success;
106 }
107 
getTestStep(const chre_settings_test_TestCommand & command,Manager::TestStep * step)108 bool getTestStep(const chre_settings_test_TestCommand &command,
109                  Manager::TestStep *step) {
110   bool success = true;
111   switch (command.step) {
112     case chre_settings_test_TestCommand_Step_SETUP:
113       *step = Manager::TestStep::SETUP;
114       break;
115     case chre_settings_test_TestCommand_Step_START:
116       *step = Manager::TestStep::START;
117       break;
118     default:
119       LOGE("Unknown test step %d", command.step);
120       success = false;
121   }
122 
123   return success;
124 }
125 
isTestSupported()126 bool isTestSupported() {
127   // CHRE settings requirements were introduced in CHRE v1.4
128   return chreGetVersion() >= CHRE_API_VERSION_1_4;
129 }
130 
131 }  // anonymous namespace
132 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)133 void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
134                           const void *eventData) {
135   if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
136     handleMessageFromHost(
137         senderInstanceId,
138         static_cast<const chreMessageFromHostData *>(eventData));
139   } else if (senderInstanceId == CHRE_INSTANCE_ID) {
140     handleDataFromChre(eventType, eventData);
141   } else {
142     LOGW("Got unknown event type from senderInstanceId %" PRIu32
143          " and with eventType %" PRIu16,
144          senderInstanceId, eventType);
145   }
146 }
147 
isFeatureSupported(Feature feature)148 bool Manager::isFeatureSupported(Feature feature) {
149   bool supported = false;
150 
151   uint32_t version = chreGetVersion();
152   switch (feature) {
153     case Feature::WIFI_SCANNING: {
154       uint32_t capabilities = chreWifiGetCapabilities();
155       supported = (version >= CHRE_API_VERSION_1_1) &&
156                   ((capabilities & CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN) != 0);
157       break;
158     }
159     case Feature::WIFI_RTT: {
160       uint32_t capabilities = chreWifiGetCapabilities();
161       supported = (version >= CHRE_API_VERSION_1_2) &&
162                   ((capabilities & CHRE_WIFI_CAPABILITIES_RTT_RANGING) != 0);
163       break;
164     }
165     case Feature::GNSS_LOCATION: {
166       uint32_t capabilities = chreGnssGetCapabilities();
167       supported = (version >= CHRE_API_VERSION_1_1) &&
168                   ((capabilities & CHRE_GNSS_CAPABILITIES_LOCATION) != 0);
169       break;
170     }
171     case Feature::GNSS_MEASUREMENT: {
172       uint32_t capabilities = chreGnssGetCapabilities();
173       supported = (version >= CHRE_API_VERSION_1_1) &&
174                   ((capabilities & CHRE_GNSS_CAPABILITIES_MEASUREMENTS) != 0);
175       break;
176     }
177     case Feature::WWAN_CELL_INFO: {
178       uint32_t capabilities = chreWwanGetCapabilities();
179       supported = (version >= CHRE_API_VERSION_1_1) &&
180                   ((capabilities & CHRE_WWAN_GET_CELL_INFO) != 0);
181       break;
182     }
183     case Feature::AUDIO: {
184       struct chreAudioSource source;
185       supported = chreAudioGetSource(0 /* handle */, &source);
186       break;
187     }
188     case Feature::BLE_SCANNING: {
189       uint32_t capabilities = chreBleGetCapabilities();
190       supported = (version >= CHRE_API_VERSION_1_7) &&
191                   ((capabilities & CHRE_BLE_CAPABILITIES_SCAN) != 0);
192       break;
193     }
194     default:
195       LOGE("Unknown feature %" PRIu8, static_cast<uint8_t>(feature));
196   }
197 
198   return supported;
199 }
200 
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)201 void Manager::handleMessageFromHost(uint32_t senderInstanceId,
202                                     const chreMessageFromHostData *hostData) {
203   bool success = false;
204   uint32_t messageType = hostData->messageType;
205   if (senderInstanceId != CHRE_INSTANCE_ID) {
206     LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
207   } else if (messageType != chre_settings_test_MessageType_TEST_COMMAND) {
208     LOGE("Invalid message type %" PRIu32, messageType);
209   } else {
210     pb_istream_t istream = pb_istream_from_buffer(
211         static_cast<const pb_byte_t *>(hostData->message),
212         hostData->messageSize);
213     chre_settings_test_TestCommand testCommand =
214         chre_settings_test_TestCommand_init_default;
215 
216     if (!pb_decode(&istream, chre_settings_test_TestCommand_fields,
217                    &testCommand)) {
218       LOGE("Failed to decode start command error %s", PB_GET_ERROR(&istream));
219     } else {
220       Feature feature;
221       FeatureState state;
222       TestStep step;
223       if (getFeature(testCommand, &feature) &&
224           getFeatureState(testCommand, &state) &&
225           getTestStep(testCommand, &step)) {
226         LOGD("starting test: feature: %u, state %u, step %u",
227              static_cast<uint8_t>(feature), static_cast<uint8_t>(state),
228              static_cast<uint8_t>(step));
229         handleStartTestMessage(hostData->hostEndpoint, feature, state, step);
230         success = true;
231       }
232     }
233   }
234 
235   if (!success) {
236     test_shared::sendTestResultToHost(
237         hostData->hostEndpoint, chre_settings_test_MessageType_TEST_RESULT,
238         false /* success */);
239   }
240 }
241 
handleStartTestMessage(uint16_t hostEndpointId,Feature feature,FeatureState state,TestStep step)242 void Manager::handleStartTestMessage(uint16_t hostEndpointId, Feature feature,
243                                      FeatureState state, TestStep step) {
244   // If the test/feature is not supported, treat as success and skip the test.
245   if (!isTestSupported() || !isFeatureSupported(feature)) {
246     LOGW("Skipping test - TestSupported: %u, FeatureSupported: %u",
247          isTestSupported(), isFeatureSupported(feature));
248     sendTestResult(hostEndpointId, true /* success */);
249   } else {
250     bool success = false;
251     if (step == TestStep::SETUP) {
252       if (feature != Feature::WIFI_RTT) {
253         LOGE("Unexpected feature %" PRIu8 " for test step",
254              static_cast<uint8_t>(feature));
255       } else {
256         success = chreWifiRequestScanAsyncDefault(&kWifiScanningCookie);
257       }
258     } else {
259       success = startTestForFeature(feature);
260     }
261 
262     if (!success) {
263       sendTestResult(hostEndpointId, false /* success */);
264     } else {
265       mTestSession = TestSession(hostEndpointId, feature, state, step);
266     }
267   }
268 }
269 
handleDataFromChre(uint16_t eventType,const void * eventData)270 void Manager::handleDataFromChre(uint16_t eventType, const void *eventData) {
271   if (mTestSession.has_value()) {
272     // The validation for the correct data w.r.t. the current test session
273     // will be done in the methods called from here.
274     switch (eventType) {
275       case CHRE_EVENT_AUDIO_DATA:
276         handleAudioDataEvent(
277             static_cast<const struct chreAudioDataEvent *>(eventData));
278         break;
279 
280       case CHRE_EVENT_AUDIO_SAMPLING_CHANGE:
281         handleAudioSourceStatusEvent(
282             static_cast<const struct chreAudioSourceStatusEvent *>(eventData));
283         break;
284 
285       case CHRE_EVENT_TIMER:
286         handleTimeout(eventData);
287         break;
288 
289       case CHRE_EVENT_WIFI_ASYNC_RESULT:
290         handleWifiAsyncResult(static_cast<const chreAsyncResult *>(eventData));
291         break;
292 
293       case CHRE_EVENT_WIFI_SCAN_RESULT:
294         handleWifiScanResult(static_cast<const chreWifiScanEvent *>(eventData));
295         break;
296 
297       case CHRE_EVENT_GNSS_ASYNC_RESULT:
298         handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData));
299         break;
300 
301       case CHRE_EVENT_WWAN_CELL_INFO_RESULT:
302         handleWwanCellInfoResult(
303             static_cast<const chreWwanCellInfoResult *>(eventData));
304         break;
305 
306       case CHRE_EVENT_BLE_ASYNC_RESULT:
307         handleBleAsyncResult(static_cast<const chreAsyncResult *>(eventData));
308         break;
309 
310       default:
311         LOGE("Unknown event type %" PRIu16, eventType);
312     }
313   }
314 }
315 
startTestForFeature(Feature feature)316 bool Manager::startTestForFeature(Feature feature) {
317   bool success = true;
318   switch (feature) {
319     case Feature::WIFI_SCANNING:
320       success = chreWifiRequestScanAsyncDefault(&kWifiScanningCookie);
321       break;
322 
323     case Feature::WIFI_RTT: {
324       if (!mCachedRangingTarget.has_value()) {
325         LOGE("No cached WiFi RTT ranging target");
326       } else {
327         struct chreWifiRangingParams params = {
328             .targetListLen = 1, .targetList = &mCachedRangingTarget.value()};
329         success = chreWifiRequestRangingAsync(&params, &kWifiRttCookie);
330       }
331       break;
332     }
333 
334     case Feature::GNSS_LOCATION:
335       success = chreGnssLocationSessionStartAsync(1000 /* minIntervalMs */,
336                                                   0 /* minTimeToNextFixMs */,
337                                                   &kGnssLocationCookie);
338       break;
339 
340     case Feature::GNSS_MEASUREMENT:
341       success = chreGnssMeasurementSessionStartAsync(1000 /* minIntervalMs */,
342                                                      &kGnssMeasurementCookie);
343       break;
344 
345     case Feature::WWAN_CELL_INFO:
346       success = chreWwanGetCellInfoAsync(&kWwanCellInfoCookie);
347       break;
348 
349     case Feature::AUDIO: {
350       struct chreAudioSource source;
351       if ((success = chreAudioGetSource(0 /* handle */, &source))) {
352         success = chreAudioConfigureSource(0 /* handle */, true /* enable */,
353                                            source.minBufferDuration,
354                                            source.minBufferDuration);
355       }
356       break;
357     }
358 
359     case Feature::BLE_SCANNING: {
360       struct chreBleScanFilter filter;
361       chreBleGenericFilter uuidFilters[kNumScanFilters];
362       createBleScanFilterForKnownBeacons(filter, uuidFilters, kNumScanFilters);
363       success = chreBleStartScanAsync(CHRE_BLE_SCAN_MODE_FOREGROUND /* mode */,
364                                       0 /* reportDelayMs */, &filter);
365       break;
366     }
367 
368     default:
369       LOGE("Unknown feature %" PRIu8, static_cast<uint8_t>(feature));
370       return false;
371   }
372 
373   if (!success) {
374     LOGE("Failed to make request for test feature %" PRIu8,
375          static_cast<uint8_t>(feature));
376   } else {
377     LOGI("Starting test for feature %" PRIu8, static_cast<uint8_t>(feature));
378   }
379 
380   return success;
381 }
382 
validateAsyncResult(const chreAsyncResult * result,const void * expectedCookie)383 bool Manager::validateAsyncResult(const chreAsyncResult *result,
384                                   const void *expectedCookie) {
385   bool success = false;
386   if (result->cookie != expectedCookie) {
387     LOGE("Unexpected cookie on async result");
388   } else {
389     bool featureEnabled = (mTestSession->featureState == FeatureState::ENABLED);
390     bool disabledErrorCode =
391         (result->errorCode == CHRE_ERROR_FUNCTION_DISABLED);
392 
393     if (featureEnabled && disabledErrorCode) {
394       LOGE("Got disabled error code when feature is enabled");
395     } else if (!featureEnabled && !disabledErrorCode) {
396       LOGE("Got non-disabled error code when feature is disabled");
397     } else {
398       success = true;
399     }
400   }
401 
402   return success;
403 }
404 
handleWifiAsyncResult(const chreAsyncResult * result)405 void Manager::handleWifiAsyncResult(const chreAsyncResult *result) {
406   bool success = false;
407   switch (result->requestType) {
408     case CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN: {
409       if (mTestSession->feature == Feature::WIFI_RTT) {
410         // Ignore validating the scan async response since we only care about
411         // the actual scan event to initiate the RTT request. A failure to
412         // receive the scan response should cause a timeout at the host.
413         return;
414       }
415       if (mTestSession->feature != Feature::WIFI_SCANNING) {
416         LOGE("Unexpected WiFi scan async result: test feature %" PRIu8,
417              static_cast<uint8_t>(mTestSession->feature));
418       } else {
419         success = validateAsyncResult(
420             result, static_cast<const void *>(&kWifiScanningCookie));
421       }
422       break;
423     }
424     case CHRE_WIFI_REQUEST_TYPE_RANGING: {
425       if (mTestSession->feature != Feature::WIFI_RTT) {
426         LOGE("Unexpected WiFi ranging async result: test feature %" PRIu8,
427              static_cast<uint8_t>(mTestSession->feature));
428       } else {
429         success = validateAsyncResult(
430             result, static_cast<const void *>(&kWifiRttCookie));
431       }
432       break;
433     }
434     default:
435       LOGE("Unexpected WiFi request type %" PRIu8, result->requestType);
436   }
437 
438   sendTestResult(mTestSession->hostEndpointId, success);
439 }
440 
handleWifiScanResult(const chreWifiScanEvent * result)441 void Manager::handleWifiScanResult(const chreWifiScanEvent *result) {
442   if (mTestSession->feature == Feature::WIFI_RTT &&
443       mTestSession->step == TestStep::SETUP) {
444     if (result->resultCount == 0) {
445       LOGE("Received empty WiFi scan result");
446       sendTestResult(mTestSession->hostEndpointId, false /* success */);
447     } else {
448       mReceivedScanResults += result->resultCount;
449       chreWifiRangingTarget target;
450       // Try to find an AP with the FTM responder flag set. The RTT ranging
451       // request should still work equivalently even if the flag is not set (but
452       // possibly with an error in the ranging result), so we use the last entry
453       // if none is found.
454       size_t index = result->resultCount - 1;
455       for (uint8_t i = 0; i < result->resultCount - 1; i++) {
456         if ((result->results[i].flags &
457              CHRE_WIFI_SCAN_RESULT_FLAGS_IS_FTM_RESPONDER) != 0) {
458           index = i;
459           break;
460         }
461       }
462       chreWifiRangingTargetFromScanResult(&result->results[index], &target);
463       mCachedRangingTarget = target;
464       if (result->resultTotal == mReceivedScanResults) {
465         mReceivedScanResults = 0;
466         test_shared::sendEmptyMessageToHost(
467             mTestSession->hostEndpointId,
468             chre_settings_test_MessageType_TEST_SETUP_COMPLETE);
469       }
470     }
471   }
472 }
473 
handleGnssAsyncResult(const chreAsyncResult * result)474 void Manager::handleGnssAsyncResult(const chreAsyncResult *result) {
475   bool success = false;
476   switch (result->requestType) {
477     case CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START: {
478       if (mTestSession->feature != Feature::GNSS_LOCATION) {
479         LOGE("Unexpected GNSS location async result: test feature %" PRIu8,
480              static_cast<uint8_t>(mTestSession->feature));
481       } else {
482         success = validateAsyncResult(
483             result, static_cast<const void *>(&kGnssLocationCookie));
484         chreGnssLocationSessionStopAsync(&kGnssLocationCookie);
485       }
486       break;
487     }
488     case CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_START: {
489       if (mTestSession->feature != Feature::GNSS_MEASUREMENT) {
490         LOGE("Unexpected GNSS measurement async result: test feature %" PRIu8,
491              static_cast<uint8_t>(mTestSession->feature));
492       } else {
493         success = validateAsyncResult(
494             result, static_cast<const void *>(&kGnssMeasurementCookie));
495         chreGnssMeasurementSessionStopAsync(&kGnssMeasurementCookie);
496       }
497       break;
498     }
499     default:
500       LOGE("Unexpected GNSS request type %" PRIu8, result->requestType);
501   }
502 
503   sendTestResult(mTestSession->hostEndpointId, success);
504 }
505 
handleWwanCellInfoResult(const chreWwanCellInfoResult * result)506 void Manager::handleWwanCellInfoResult(const chreWwanCellInfoResult *result) {
507   bool success = false;
508   // For WWAN, we treat "DISABLED" as success but with empty results, per
509   // CHRE API requirements.
510   if (mTestSession->feature != Feature::WWAN_CELL_INFO) {
511     LOGE("Unexpected WWAN cell info result: test feature %" PRIu8,
512          static_cast<uint8_t>(mTestSession->feature));
513   } else if (result->cookie != &kWwanCellInfoCookie) {
514     LOGE("Unexpected cookie on WWAN cell info result");
515   } else if (result->errorCode != CHRE_ERROR_NONE) {
516     LOGE("WWAN cell info result failed: error code %" PRIu8, result->errorCode);
517   } else if (mTestSession->featureState == FeatureState::DISABLED &&
518              result->cellInfoCount > 0) {
519     LOGE("WWAN cell info result should be empty when disabled: count %" PRIu8,
520          result->cellInfoCount);
521   } else {
522     success = true;
523   }
524 
525   sendTestResult(mTestSession->hostEndpointId, success);
526 }
527 
528 // The MicDisabled Settings test works as follows:
529 // * The contents of the Source Status Event are parsed, and there are 4
530 //   possible scenarios for the flow of our test:
531 //
532 // - Mic Access was disabled, source was suspended
533 // -- Since CHRE guarantees that we'll receive audio data events spaced at
534 //    the source's minBufferDuration apart (plus a small delay/latency),
535 //    we set a timer for (minBufferDuration + 1) seconds to verify that no
536 //    data event was received. We pass the test on a timeout.
537 //
538 // - Mic Access was disabled, source wasn't suspended
539 // -- We fail the test
540 //
541 // - Mic Access was enabled, source was suspended
542 // -- We fail the test
543 //
544 // - Mic Access was enabled, source wasn't suspended
545 // -- We set a flag 'GotSourceEnabledEvent'. The audio data event checks this
546 // flag, and reports success/failure appropriately.
547 
handleAudioSourceStatusEvent(const struct chreAudioSourceStatusEvent * event)548 void Manager::handleAudioSourceStatusEvent(
549     const struct chreAudioSourceStatusEvent *event) {
550   bool success = false;
551   if (mTestSession.has_value()) {
552     if (mTestSession->featureState == FeatureState::ENABLED) {
553       if (event->status.suspended) {
554         struct chreAudioSource source;
555         if (chreAudioGetSource(0 /* handle */, &source)) {
556           const uint64_t duration =
557               source.minBufferDuration + kOneSecondInNanoseconds;
558           gAudioDataTimerHandle = chreTimerSet(duration, &kAudioDataTimerCookie,
559                                                true /* oneShot */);
560 
561           if (gAudioDataTimerHandle == CHRE_TIMER_INVALID) {
562             LOGE("Failed to set data check timer");
563           } else {
564             success = true;
565           }
566         } else {
567           LOGE("Failed to query audio source");
568         }
569       } else {
570         // There might be a corner case where CHRE might have queued an audio
571         // available event just as the microphone disable setting change is
572         // received that might wrongfully indicate that microphone access
573         // wasn't disabled when it is dispatched. We add a 2 second timer to
574         // allow CHRE to send the source status change event to account for
575         // this, and fail the test if the timer expires without getting said
576         // event.
577         LOGW("Source wasn't suspended when Mic Access disabled, waiting 2 sec");
578         gAudioStatusTimerHandle =
579             chreTimerSet(2 * kOneSecondInNanoseconds, &kAudioStatusTimerCookie,
580                          true /* oneShot */);
581         if (gAudioStatusTimerHandle == CHRE_TIMER_INVALID) {
582           LOGE("Failed to set audio status check timer");
583         } else {
584           // continue the test, fail on timeout.
585           success = true;
586         }
587       }
588     } else {
589       gGotSourceEnabledEvent = true;
590       success = true;
591     }
592 
593     if (!success) {
594       sendTestResult(mTestSession->hostEndpointId, success);
595     }
596   }
597 }
598 
handleAudioDataEvent(const struct chreAudioDataEvent * event)599 void Manager::handleAudioDataEvent(const struct chreAudioDataEvent *event) {
600   UNUSED_VAR(event);
601 
602   bool success = false;
603   if (mTestSession.has_value()) {
604     if (mTestSession->featureState == FeatureState::ENABLED) {
605       if (gAudioDataTimerHandle != CHRE_TIMER_INVALID) {
606         chreTimerCancel(gAudioDataTimerHandle);
607         gAudioDataTimerHandle = CHRE_TIMER_INVALID;
608       }
609     } else if (gGotSourceEnabledEvent) {
610       success = true;
611     }
612     chreAudioConfigureSource(0 /* handle */, false /* enable */,
613                              0 /* minBufferDuration */,
614                              0 /* maxbufferDuration */);
615     sendTestResult(mTestSession->hostEndpointId, success);
616   }
617 }
618 
handleTimeout(const void * eventData)619 void Manager::handleTimeout(const void *eventData) {
620   bool testSuccess = false;
621   auto *cookie = static_cast<const uint32_t *>(eventData);
622 
623   if (*cookie == kAudioDataTimerCookie) {
624     gAudioDataTimerHandle = CHRE_TIMER_INVALID;
625     testSuccess = true;
626     if (gAudioStatusTimerHandle != CHRE_TIMER_INVALID) {
627       chreTimerCancel(gAudioStatusTimerHandle);
628       gAudioStatusTimerHandle = CHRE_TIMER_INVALID;
629     }
630   } else if (*cookie == kAudioStatusTimerCookie) {
631     LOGE("Source wasn't suspended when Mic Access was disabled");
632     gAudioStatusTimerHandle = CHRE_TIMER_INVALID;
633     testSuccess = false;
634   } else {
635     LOGE("Invalid timer cookie: %" PRIx32, *cookie);
636   }
637   chreAudioConfigureSource(0 /*handle*/, false /*enable*/,
638                            0 /*minBufferDuration*/, 0 /*maxBufferDuration*/);
639   sendTestResult(mTestSession->hostEndpointId, testSuccess);
640 }
641 
handleBleAsyncResult(const chreAsyncResult * result)642 void Manager::handleBleAsyncResult(const chreAsyncResult *result) {
643   bool success = false;
644   switch (result->requestType) {
645     case CHRE_BLE_REQUEST_TYPE_START_SCAN: {
646       if (mTestSession->feature != Feature::BLE_SCANNING) {
647         LOGE("Unexpected BLE scan async result: test feature %" PRIu8,
648              static_cast<uint8_t>(mTestSession->feature));
649       } else {
650         success = validateAsyncResult(result, nullptr);
651       }
652       break;
653     }
654     default:
655       LOGE("Unexpected BLE request type %" PRIu8, result->requestType);
656   }
657 
658   sendTestResult(mTestSession->hostEndpointId, success);
659 }
660 
sendTestResult(uint16_t hostEndpointId,bool success)661 void Manager::sendTestResult(uint16_t hostEndpointId, bool success) {
662   test_shared::sendTestResultToHost(
663       hostEndpointId, chre_settings_test_MessageType_TEST_RESULT, success);
664   mTestSession.reset();
665   mCachedRangingTarget.reset();
666 }
667 
668 }  // namespace settings_test
669 
670 }  // namespace chre
671