• 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/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