xref: /aosp_15_r20/system/chre/platform/linux/pal_wifi.cc (revision 84e339476a462649f82315436d70fd732297a399)
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/platform/linux/pal_wifi.h"
18 
19 #include <atomic>
20 #include <chrono>
21 #include <cinttypes>
22 #include <optional>
23 
24 #include "chre/pal/wifi.h"
25 #include "chre/platform/linux/pal_nan.h"
26 #include "chre/platform/linux/task_util/task_manager.h"
27 #include "chre/util/enum.h"
28 #include "chre/util/memory.h"
29 #include "chre/util/time.h"
30 #include "chre/util/unique_ptr.h"
31 
32 /**
33  * A simulated implementation of the WiFi PAL for the linux platform.
34  */
35 namespace {
36 
37 using ::chre::TaskManagerSingleton;
38 
39 const struct chrePalSystemApi *gSystemApi = nullptr;
40 const struct chrePalWifiCallbacks *gCallbacks = nullptr;
41 
42 //! Whether scan monitoring is active.
43 std::atomic_bool gScanMonitoringActive(false);
44 
45 //! Whether PAL should respond to RRT ranging request.
46 std::atomic_bool gEnableRangingResponse(true);
47 
48 //! Whether PAL should respond to configure scan monitor request.
49 std::atomic_bool gEnableScanMonitorResponse(true);
50 
51 //! Whether PAL should respond to scan request.
52 std::atomic_bool gEnableScanResponse(true);
53 
54 //! Thread sync variable for TaskIds.
55 std::mutex gRequestScanMutex;
56 
57 //! Task IDs for the scanning tasks
58 std::optional<uint32_t> gScanMonitorTaskId;
59 std::optional<uint32_t> gRequestScanTaskId;
60 std::optional<uint32_t> gRequestRangingTaskId;
61 
62 //! How long should each the PAL hold before response.
63 //! Use to mimic real world hardware process time.
64 std::chrono::nanoseconds gAsyncRequestDelayResponseTime[chre::asBaseType(
65     PalWifiAsyncRequestTypes::NUM_WIFI_REQUEST_TYPE)];
66 
sendScanResponse()67 void sendScanResponse() {
68   {
69     std::lock_guard<std::mutex> lock(gRequestScanMutex);
70     if (!gRequestScanTaskId.has_value()) {
71       LOGE("Sending scan response with no pending task");
72       return;
73     }
74     gRequestScanTaskId.reset();
75   }
76 
77   if (gEnableScanResponse) {
78     auto event = chre::MakeUniqueZeroFill<struct chreWifiScanEvent>();
79     auto result = chre::MakeUniqueZeroFill<struct chreWifiScanResult>();
80     event->resultCount = 1;
81     event->resultTotal = 1;
82     event->referenceTime = gSystemApi->getCurrentTime();
83     event->results = result.release();
84     gCallbacks->scanEventCallback(event.release());
85   }
86 }
87 
sendScanMonitorResponse(bool enable)88 void sendScanMonitorResponse(bool enable) {
89   if (gEnableScanMonitorResponse) {
90     gCallbacks->scanMonitorStatusChangeCallback(enable, CHRE_ERROR_NONE);
91   }
92 }
93 
sendRangingResponse()94 void sendRangingResponse() {
95   if (gEnableRangingResponse) {
96     auto event = chre::MakeUniqueZeroFill<struct chreWifiRangingEvent>();
97     auto result = chre::MakeUniqueZeroFill<struct chreWifiRangingResult>();
98     event->resultCount = 1;
99     event->results = result.release();
100     gCallbacks->rangingEventCallback(CHRE_ERROR_NONE, event.release());
101   }
102 }
103 
stopScanMonitorTask()104 void stopScanMonitorTask() {
105   if (gScanMonitorTaskId.has_value()) {
106     TaskManagerSingleton::get()->cancelTask(gScanMonitorTaskId.value());
107     gScanMonitorTaskId.reset();
108   }
109 }
110 
stopRequestScanTask()111 void stopRequestScanTask() {
112   if (gRequestScanTaskId.has_value()) {
113     TaskManagerSingleton::get()->cancelTask(gRequestScanTaskId.value());
114     gRequestScanTaskId.reset();
115   }
116 }
117 
stopRequestRangingTask()118 void stopRequestRangingTask() {
119   if (gRequestRangingTaskId.has_value()) {
120     TaskManagerSingleton::get()->cancelTask(gRequestRangingTaskId.value());
121     gRequestRangingTaskId.reset();
122   }
123 }
124 
chrePalWifiGetCapabilities()125 uint32_t chrePalWifiGetCapabilities() {
126   return CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
127          CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN | CHRE_WIFI_CAPABILITIES_NAN_SUB;
128 }
129 
chrePalWifiConfigureScanMonitor(bool enable)130 bool chrePalWifiConfigureScanMonitor(bool enable) {
131   stopScanMonitorTask();
132 
133   gScanMonitorTaskId = TaskManagerSingleton::get()->addTask(
134       [enable]() { sendScanMonitorResponse(enable); });
135   gScanMonitoringActive = enable;
136   return gScanMonitorTaskId.has_value();
137 }
138 
chrePalWifiApiRequestScan(const struct chreWifiScanParams *)139 bool chrePalWifiApiRequestScan(const struct chreWifiScanParams * /* params */) {
140   std::lock_guard<std::mutex> lock(gRequestScanMutex);
141   if (gRequestScanTaskId.has_value()) {
142     LOGE("Requesting scan when existing scan request still in process");
143     return false;
144   }
145 
146   std::optional<uint32_t> requestScanTaskCallbackId =
147       TaskManagerSingleton::get()->addTask([]() {
148         if (gEnableScanResponse) {
149           gCallbacks->scanResponseCallback(true, CHRE_ERROR_NONE);
150         }
151       });
152   if (requestScanTaskCallbackId.has_value()) {
153     gRequestScanTaskId = TaskManagerSingleton::get()->addTask(
154         sendScanResponse,
155         gAsyncRequestDelayResponseTime[chre::asBaseType(
156             PalWifiAsyncRequestTypes::SCAN)],
157         /* isOneShot= */ true);
158     return gRequestScanTaskId.has_value();
159   }
160   return false;
161 }
162 
chrePalWifiApiRequestRanging(const struct chreWifiRangingParams *)163 bool chrePalWifiApiRequestRanging(
164     const struct chreWifiRangingParams * /* params */) {
165   stopRequestRangingTask();
166 
167   gRequestRangingTaskId =
168       TaskManagerSingleton::get()->addTask(sendRangingResponse);
169   return gRequestRangingTaskId.has_value();
170 }
171 
chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent * event)172 void chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent *event) {
173   chre::memoryFree(const_cast<uint32_t *>(event->scannedFreqList));
174   chre::memoryFree(const_cast<struct chreWifiScanResult *>(event->results));
175   chre::memoryFree(event);
176 }
177 
chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent * event)178 void chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent *event) {
179   chre::memoryFree(const_cast<struct chreWifiRangingResult *>(event->results));
180   chre::memoryFree(event);
181 }
182 
chrePalWifiApiNanSubscribe(const struct chreWifiNanSubscribeConfig * config)183 bool chrePalWifiApiNanSubscribe(
184     const struct chreWifiNanSubscribeConfig *config) {
185   uint32_t subscriptionId = 0;
186   uint8_t errorCode =
187       chre::PalNanEngineSingleton::get()->subscribe(config, &subscriptionId);
188 
189   gCallbacks->nanServiceIdentifierCallback(errorCode, subscriptionId);
190 
191   return true;
192 }
193 
chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId)194 bool chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId) {
195   gCallbacks->nanSubscriptionCanceledCallback(CHRE_ERROR_NONE, subscriptionId);
196   return chre::PalNanEngineSingleton::get()->subscribeCancel(subscriptionId);
197 }
198 
chrePalWifiApiNanReleaseDiscoveryEvent(struct chreWifiNanDiscoveryEvent * event)199 void chrePalWifiApiNanReleaseDiscoveryEvent(
200     struct chreWifiNanDiscoveryEvent *event) {
201   chre::PalNanEngineSingleton::get()->destroyDiscoveryEvent(event);
202 }
203 
chrePalWifiApiRequestNanRanging(const struct chreWifiNanRangingParams * params)204 bool chrePalWifiApiRequestNanRanging(
205     const struct chreWifiNanRangingParams *params) {
206   constexpr uint32_t kFakeRangeMeasurementMm = 1000;
207 
208   auto *event = chre::memoryAlloc<struct chreWifiRangingEvent>();
209   CHRE_ASSERT_NOT_NULL(event);
210 
211   auto *result = chre::memoryAlloc<struct chreWifiRangingResult>();
212   CHRE_ASSERT_NOT_NULL(result);
213 
214   std::memcpy(result->macAddress, params->macAddress, CHRE_WIFI_BSSID_LEN);
215   result->status = CHRE_WIFI_RANGING_STATUS_SUCCESS;
216   result->distance = kFakeRangeMeasurementMm;
217   event->resultCount = 1;
218   event->results = result;
219 
220   gCallbacks->rangingEventCallback(CHRE_ERROR_NONE, event);
221 
222   return true;
223 }
224 
chrePalWifiApiClose()225 void chrePalWifiApiClose() {
226   stopScanMonitorTask();
227   stopRequestScanTask();
228   stopRequestRangingTask();
229 }
230 
chrePalWifiApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWifiCallbacks * callbacks)231 bool chrePalWifiApiOpen(const struct chrePalSystemApi *systemApi,
232                         const struct chrePalWifiCallbacks *callbacks) {
233   chrePalWifiApiClose();
234 
235   bool success = false;
236   if (systemApi != nullptr && callbacks != nullptr) {
237     gSystemApi = systemApi;
238     gCallbacks = callbacks;
239 
240     chre::PalNanEngineSingleton::get()->setPlatformWifiCallbacks(callbacks);
241 
242     success = true;
243   }
244 
245   return success;
246 }
247 
chrePalWifiNanGetCapabilities(struct chreWifiNanCapabilities *)248 bool chrePalWifiNanGetCapabilities(
249     struct chreWifiNanCapabilities * /* capabilities */) {
250   return false;
251 }
252 
253 }  // anonymous namespace
254 
chrePalWifiEnableResponse(PalWifiAsyncRequestTypes requestType,bool enableResponse)255 void chrePalWifiEnableResponse(PalWifiAsyncRequestTypes requestType,
256                                bool enableResponse) {
257   switch (requestType) {
258     case PalWifiAsyncRequestTypes::RANGING:
259       gEnableRangingResponse = enableResponse;
260       break;
261 
262     case PalWifiAsyncRequestTypes::SCAN_MONITORING:
263       gEnableScanMonitorResponse = enableResponse;
264       break;
265 
266     case PalWifiAsyncRequestTypes::SCAN:
267       gEnableScanResponse = enableResponse;
268       break;
269 
270     default:
271       LOGE("Cannot enable/disable request type: %" PRIu8,
272            static_cast<uint8_t>(requestType));
273   }
274 }
275 
chrePalWifiIsScanMonitoringActive()276 bool chrePalWifiIsScanMonitoringActive() {
277   return gScanMonitoringActive;
278 }
279 
chrePalWifiDelayResponse(PalWifiAsyncRequestTypes requestType,std::chrono::milliseconds milliseconds)280 void chrePalWifiDelayResponse(PalWifiAsyncRequestTypes requestType,
281                               std::chrono::milliseconds milliseconds) {
282   gAsyncRequestDelayResponseTime[chre::asBaseType(requestType)] =
283       std::chrono::duration_cast<std::chrono::nanoseconds>(milliseconds);
284   ;
285 }
286 
chrePalWifiGetApi(uint32_t requestedApiVersion)287 const struct chrePalWifiApi *chrePalWifiGetApi(uint32_t requestedApiVersion) {
288   static const struct chrePalWifiApi kApi = {
289       .moduleVersion = CHRE_PAL_WIFI_API_CURRENT_VERSION,
290       .open = chrePalWifiApiOpen,
291       .close = chrePalWifiApiClose,
292       .getCapabilities = chrePalWifiGetCapabilities,
293       .configureScanMonitor = chrePalWifiConfigureScanMonitor,
294       .requestScan = chrePalWifiApiRequestScan,
295       .releaseScanEvent = chrePalWifiApiReleaseScanEvent,
296       .requestRanging = chrePalWifiApiRequestRanging,
297       .releaseRangingEvent = chrePalWifiApiReleaseRangingEvent,
298       .nanSubscribe = chrePalWifiApiNanSubscribe,
299       .nanSubscribeCancel = chrePalWifiApiNanSubscribeCancel,
300       .releaseNanDiscoveryEvent = chrePalWifiApiNanReleaseDiscoveryEvent,
301       .requestNanRanging = chrePalWifiApiRequestNanRanging,
302       .getNanCapabilities = chrePalWifiNanGetCapabilities,
303   };
304 
305   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
306                                         requestedApiVersion)) {
307     return nullptr;
308   } else {
309     chre::PalNanEngineSingleton::init();
310     return &kApi;
311   }
312 }
313