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 //! Task IDs for the scanning tasks
55 std::optional<uint32_t> gScanMonitorTaskId;
56 std::optional<uint32_t> gRequestScanTaskId;
57 std::optional<uint32_t> gRequestRangingTaskId;
58
59 //! How long should each the PAL hold before response.
60 //! Use to mimic real world hardware process time.
61 std::chrono::milliseconds gAsyncRequestDelayResponseTime[chre::asBaseType(
62 PalWifiAsyncRequestTypes::NUM_WIFI_REQUEST_TYPE)];
63
sendScanResponse()64 void sendScanResponse() {
65 if (gEnableScanResponse) {
66 auto event = chre::MakeUniqueZeroFill<struct chreWifiScanEvent>();
67 auto result = chre::MakeUniqueZeroFill<struct chreWifiScanResult>();
68 event->resultCount = 1;
69 event->resultTotal = 1;
70 event->referenceTime = gSystemApi->getCurrentTime();
71 event->results = result.release();
72 gCallbacks->scanEventCallback(event.release());
73 }
74
75 // We just want to delay this task - only execute it once.
76 TaskManagerSingleton::get()->cancelTask(gRequestScanTaskId.value());
77 }
78
sendScanMonitorResponse(bool enable)79 void sendScanMonitorResponse(bool enable) {
80 if (gEnableScanMonitorResponse) {
81 gCallbacks->scanMonitorStatusChangeCallback(enable, CHRE_ERROR_NONE);
82 }
83 }
84
sendRangingResponse()85 void sendRangingResponse() {
86 if (gEnableRangingResponse) {
87 auto event = chre::MakeUniqueZeroFill<struct chreWifiRangingEvent>();
88 auto result = chre::MakeUniqueZeroFill<struct chreWifiRangingResult>();
89 event->resultCount = 1;
90 event->results = result.release();
91 gCallbacks->rangingEventCallback(CHRE_ERROR_NONE, event.release());
92 }
93 }
94
stopScanMonitorTask()95 void stopScanMonitorTask() {
96 if (gScanMonitorTaskId.has_value()) {
97 TaskManagerSingleton::get()->cancelTask(gScanMonitorTaskId.value());
98 }
99 }
100
stopRequestScanTask()101 void stopRequestScanTask() {
102 if (gRequestScanTaskId.has_value()) {
103 TaskManagerSingleton::get()->cancelTask(gRequestScanTaskId.value());
104 }
105 }
106
stopRequestRangingTask()107 void stopRequestRangingTask() {
108 if (gRequestRangingTaskId.has_value()) {
109 TaskManagerSingleton::get()->cancelTask(gRequestRangingTaskId.value());
110 }
111 }
112
chrePalWifiGetCapabilities()113 uint32_t chrePalWifiGetCapabilities() {
114 return CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
115 CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN | CHRE_WIFI_CAPABILITIES_NAN_SUB;
116 }
117
chrePalWifiConfigureScanMonitor(bool enable)118 bool chrePalWifiConfigureScanMonitor(bool enable) {
119 stopScanMonitorTask();
120
121 gScanMonitorTaskId = TaskManagerSingleton::get()->addTask(
122 [enable]() { sendScanMonitorResponse(enable); });
123 gScanMonitoringActive = enable;
124 return gScanMonitorTaskId.has_value();
125 }
126
chrePalWifiApiRequestScan(const struct chreWifiScanParams *)127 bool chrePalWifiApiRequestScan(const struct chreWifiScanParams * /* params */) {
128 stopRequestScanTask();
129
130 std::optional<uint32_t> requestScanTaskCallbackId =
131 TaskManagerSingleton::get()->addTask([]() {
132 if (gEnableScanResponse) {
133 gCallbacks->scanResponseCallback(true, CHRE_ERROR_NONE);
134 }
135 });
136 if (requestScanTaskCallbackId.has_value()) {
137 gRequestScanTaskId = TaskManagerSingleton::get()->addTask(
138 sendScanResponse, gAsyncRequestDelayResponseTime[chre::asBaseType(
139 PalWifiAsyncRequestTypes::SCAN)]);
140 return gRequestScanTaskId.has_value();
141 }
142 return false;
143 }
144
chrePalWifiApiRequestRanging(const struct chreWifiRangingParams *)145 bool chrePalWifiApiRequestRanging(
146 const struct chreWifiRangingParams * /* params */) {
147 stopRequestRangingTask();
148
149 gRequestRangingTaskId =
150 TaskManagerSingleton::get()->addTask(sendRangingResponse);
151 return gRequestRangingTaskId.has_value();
152 }
153
chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent * event)154 void chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent *event) {
155 chre::memoryFree(const_cast<uint32_t *>(event->scannedFreqList));
156 chre::memoryFree(const_cast<struct chreWifiScanResult *>(event->results));
157 chre::memoryFree(event);
158 }
159
chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent * event)160 void chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent *event) {
161 chre::memoryFree(const_cast<struct chreWifiRangingResult *>(event->results));
162 chre::memoryFree(event);
163 }
164
chrePalWifiApiNanSubscribe(const struct chreWifiNanSubscribeConfig * config)165 bool chrePalWifiApiNanSubscribe(
166 const struct chreWifiNanSubscribeConfig *config) {
167 uint32_t subscriptionId = 0;
168 uint8_t errorCode =
169 chre::PalNanEngineSingleton::get()->subscribe(config, &subscriptionId);
170
171 gCallbacks->nanServiceIdentifierCallback(errorCode, subscriptionId);
172
173 return true;
174 }
175
chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId)176 bool chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId) {
177 gCallbacks->nanSubscriptionCanceledCallback(CHRE_ERROR_NONE, subscriptionId);
178 return chre::PalNanEngineSingleton::get()->subscribeCancel(subscriptionId);
179 }
180
chrePalWifiApiNanReleaseDiscoveryEvent(struct chreWifiNanDiscoveryEvent * event)181 void chrePalWifiApiNanReleaseDiscoveryEvent(
182 struct chreWifiNanDiscoveryEvent *event) {
183 chre::PalNanEngineSingleton::get()->destroyDiscoveryEvent(event);
184 }
185
chrePalWifiApiRequestNanRanging(const struct chreWifiNanRangingParams * params)186 bool chrePalWifiApiRequestNanRanging(
187 const struct chreWifiNanRangingParams *params) {
188 constexpr uint32_t kFakeRangeMeasurementMm = 1000;
189
190 auto *event = chre::memoryAlloc<struct chreWifiRangingEvent>();
191 CHRE_ASSERT_NOT_NULL(event);
192
193 auto *result = chre::memoryAlloc<struct chreWifiRangingResult>();
194 CHRE_ASSERT_NOT_NULL(result);
195
196 std::memcpy(result->macAddress, params->macAddress, CHRE_WIFI_BSSID_LEN);
197 result->status = CHRE_WIFI_RANGING_STATUS_SUCCESS;
198 result->distance = kFakeRangeMeasurementMm;
199 event->resultCount = 1;
200 event->results = result;
201
202 gCallbacks->rangingEventCallback(CHRE_ERROR_NONE, event);
203
204 return true;
205 }
206
chrePalWifiApiClose()207 void chrePalWifiApiClose() {
208 stopScanMonitorTask();
209 stopRequestScanTask();
210 stopRequestRangingTask();
211 }
212
chrePalWifiApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWifiCallbacks * callbacks)213 bool chrePalWifiApiOpen(const struct chrePalSystemApi *systemApi,
214 const struct chrePalWifiCallbacks *callbacks) {
215 chrePalWifiApiClose();
216
217 bool success = false;
218 if (systemApi != nullptr && callbacks != nullptr) {
219 gSystemApi = systemApi;
220 gCallbacks = callbacks;
221
222 chre::PalNanEngineSingleton::get()->setPlatformWifiCallbacks(callbacks);
223
224 success = true;
225 }
226
227 return success;
228 }
229
230 } // anonymous namespace
231
chrePalWifiEnableResponse(PalWifiAsyncRequestTypes requestType,bool enableResponse)232 void chrePalWifiEnableResponse(PalWifiAsyncRequestTypes requestType,
233 bool enableResponse) {
234 switch (requestType) {
235 case PalWifiAsyncRequestTypes::RANGING:
236 gEnableRangingResponse = enableResponse;
237 break;
238
239 case PalWifiAsyncRequestTypes::SCAN_MONITORING:
240 gEnableScanMonitorResponse = enableResponse;
241 break;
242
243 case PalWifiAsyncRequestTypes::SCAN:
244 gEnableScanResponse = enableResponse;
245 break;
246
247 default:
248 LOGE("Cannot enable/disable request type: %" PRIu8,
249 static_cast<uint8_t>(requestType));
250 }
251 }
252
chrePalWifiIsScanMonitoringActive()253 bool chrePalWifiIsScanMonitoringActive() {
254 return gScanMonitoringActive;
255 }
256
chrePalWifiDelayResponse(PalWifiAsyncRequestTypes requestType,std::chrono::seconds seconds)257 void chrePalWifiDelayResponse(PalWifiAsyncRequestTypes requestType,
258 std::chrono::seconds seconds) {
259 gAsyncRequestDelayResponseTime[chre::asBaseType(requestType)] =
260 std::chrono::duration_cast<std::chrono::milliseconds>(seconds);
261 }
262
chrePalWifiGetApi(uint32_t requestedApiVersion)263 const struct chrePalWifiApi *chrePalWifiGetApi(uint32_t requestedApiVersion) {
264 static const struct chrePalWifiApi kApi = {
265 .moduleVersion = CHRE_PAL_WIFI_API_CURRENT_VERSION,
266 .open = chrePalWifiApiOpen,
267 .close = chrePalWifiApiClose,
268 .getCapabilities = chrePalWifiGetCapabilities,
269 .configureScanMonitor = chrePalWifiConfigureScanMonitor,
270 .requestScan = chrePalWifiApiRequestScan,
271 .releaseScanEvent = chrePalWifiApiReleaseScanEvent,
272 .requestRanging = chrePalWifiApiRequestRanging,
273 .releaseRangingEvent = chrePalWifiApiReleaseRangingEvent,
274 .nanSubscribe = chrePalWifiApiNanSubscribe,
275 .nanSubscribeCancel = chrePalWifiApiNanSubscribeCancel,
276 .releaseNanDiscoveryEvent = chrePalWifiApiNanReleaseDiscoveryEvent,
277 .requestNanRanging = chrePalWifiApiRequestNanRanging,
278 };
279
280 if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
281 requestedApiVersion)) {
282 return nullptr;
283 } else {
284 chre::PalNanEngineSingleton::init();
285 return &kApi;
286 }
287 }
288