• 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/pal/wifi.h"
18 
19 #include "chre/util/memory.h"
20 #include "chre/util/unique_ptr.h"
21 
22 #include "chre/platform/linux/pal_nan.h"
23 
24 #include <chrono>
25 #include <cinttypes>
26 #include <thread>
27 
28 /**
29  * A simulated implementation of the WiFi PAL for the linux platform.
30  */
31 namespace {
32 const struct chrePalSystemApi *gSystemApi = nullptr;
33 const struct chrePalWifiCallbacks *gCallbacks = nullptr;
34 
35 //! Thread to deliver asynchronous WiFi scan results after a CHRE request.
36 std::thread gScanEventsThread;
37 
38 //! Thread to use when delivering a scan monitor status update.
39 std::thread gScanMonitorStatusThread;
40 
41 //! Whether scan monitoring is active.
42 bool gScanMonitoringActive = false;
43 
sendScanResponse()44 void sendScanResponse() {
45   gCallbacks->scanResponseCallback(true, CHRE_ERROR_NONE);
46 
47   auto event = chre::MakeUniqueZeroFill<struct chreWifiScanEvent>();
48   auto result = chre::MakeUniqueZeroFill<struct chreWifiScanResult>();
49   event->resultCount = 1;
50   event->resultTotal = 1;
51   event->referenceTime = gSystemApi->getCurrentTime();
52   event->results = result.release();
53 
54   gCallbacks->scanEventCallback(event.release());
55 }
56 
sendScanMonitorResponse(bool enable)57 void sendScanMonitorResponse(bool enable) {
58   gCallbacks->scanMonitorStatusChangeCallback(enable, CHRE_ERROR_NONE);
59 }
60 
stopScanEventThreads()61 void stopScanEventThreads() {
62   if (gScanEventsThread.joinable()) {
63     gScanEventsThread.join();
64   }
65 }
66 
stopScanMonitorThreads()67 void stopScanMonitorThreads() {
68   if (gScanMonitorStatusThread.joinable()) {
69     gScanMonitorStatusThread.join();
70   }
71 }
72 
chrePalWifiGetCapabilities()73 uint32_t chrePalWifiGetCapabilities() {
74   return CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
75          CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN | CHRE_WIFI_CAPABILITIES_NAN_SUB;
76 }
77 
chrePalWifiConfigureScanMonitor(bool enable)78 bool chrePalWifiConfigureScanMonitor(bool enable) {
79   stopScanMonitorThreads();
80 
81   gScanMonitorStatusThread = std::thread(sendScanMonitorResponse, enable);
82   gScanMonitoringActive = enable;
83 
84   return true;
85 }
86 
chrePalWifiApiRequestScan(const struct chreWifiScanParams *)87 bool chrePalWifiApiRequestScan(const struct chreWifiScanParams * /* params */) {
88   stopScanEventThreads();
89 
90   gScanEventsThread = std::thread(sendScanResponse);
91 
92   return true;
93 }
94 
chrePalWifiApiRequestRanging(const struct chreWifiRangingParams *)95 bool chrePalWifiApiRequestRanging(
96     const struct chreWifiRangingParams * /* params */) {
97   // unimplemented
98   return false;
99 }
100 
chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent * event)101 void chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent *event) {
102   chre::memoryFree(const_cast<uint32_t *>(event->scannedFreqList));
103   chre::memoryFree(const_cast<struct chreWifiScanResult *>(event->results));
104   chre::memoryFree(event);
105 }
106 
chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent * event)107 void chrePalWifiApiReleaseRangingEvent(struct chreWifiRangingEvent *event) {
108   chre::memoryFree(const_cast<struct chreWifiRangingResult *>(event->results));
109   chre::memoryFree(event);
110 }
111 
chrePalWifiApiNanSubscribe(const struct chreWifiNanSubscribeConfig * config)112 bool chrePalWifiApiNanSubscribe(
113     const struct chreWifiNanSubscribeConfig *config) {
114   uint32_t subscriptionId = 0;
115   uint8_t errorCode =
116       chre::PalNanEngineSingleton::get()->subscribe(config, &subscriptionId);
117 
118   gCallbacks->nanServiceIdentifierCallback(errorCode, subscriptionId);
119 
120   return true;
121 }
122 
chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId)123 bool chrePalWifiApiNanSubscribeCancel(const uint32_t subscriptionId) {
124   gCallbacks->nanSubscriptionCanceledCallback(CHRE_ERROR_NONE, subscriptionId);
125   return chre::PalNanEngineSingleton::get()->subscribeCancel(subscriptionId);
126 }
127 
chrePalWifiApiNanReleaseDiscoveryEvent(struct chreWifiNanDiscoveryEvent * event)128 void chrePalWifiApiNanReleaseDiscoveryEvent(
129     struct chreWifiNanDiscoveryEvent *event) {
130   chre::PalNanEngineSingleton::get()->destroyDiscoveryEvent(event);
131 }
132 
chrePalWifiApiRequestNanRanging(const struct chreWifiNanRangingParams * params)133 bool chrePalWifiApiRequestNanRanging(
134     const struct chreWifiNanRangingParams *params) {
135   constexpr uint32_t kFakeRangeMeasurementMm = 1000;
136 
137   auto *event = chre::memoryAlloc<struct chreWifiRangingEvent>();
138   CHRE_ASSERT_NOT_NULL(event);
139 
140   auto *result = chre::memoryAlloc<struct chreWifiRangingResult>();
141   CHRE_ASSERT_NOT_NULL(result);
142 
143   std::memcpy(result->macAddress, params->macAddress, CHRE_WIFI_BSSID_LEN);
144   result->status = CHRE_WIFI_RANGING_STATUS_SUCCESS;
145   result->distance = kFakeRangeMeasurementMm;
146   event->resultCount = 1;
147   event->results = result;
148 
149   gCallbacks->rangingEventCallback(CHRE_ERROR_NONE, event);
150 
151   return true;
152 }
153 
chrePalWifiApiClose()154 void chrePalWifiApiClose() {
155   stopScanEventThreads();
156   stopScanMonitorThreads();
157 }
158 
chrePalWifiApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWifiCallbacks * callbacks)159 bool chrePalWifiApiOpen(const struct chrePalSystemApi *systemApi,
160                         const struct chrePalWifiCallbacks *callbacks) {
161   chrePalWifiApiClose();
162 
163   bool success = false;
164   if (systemApi != nullptr && callbacks != nullptr) {
165     gSystemApi = systemApi;
166     gCallbacks = callbacks;
167 
168     chre::PalNanEngineSingleton::get()->setPlatformWifiCallbacks(callbacks);
169 
170     success = true;
171   }
172 
173   return success;
174 }
175 
176 }  // anonymous namespace
177 
chrePalWifiIsScanMonitoringActive()178 bool chrePalWifiIsScanMonitoringActive() {
179   return gScanMonitoringActive;
180 }
181 
chrePalWifiGetApi(uint32_t requestedApiVersion)182 const struct chrePalWifiApi *chrePalWifiGetApi(uint32_t requestedApiVersion) {
183   static const struct chrePalWifiApi kApi = {
184       .moduleVersion = CHRE_PAL_WIFI_API_CURRENT_VERSION,
185       .open = chrePalWifiApiOpen,
186       .close = chrePalWifiApiClose,
187       .getCapabilities = chrePalWifiGetCapabilities,
188       .configureScanMonitor = chrePalWifiConfigureScanMonitor,
189       .requestScan = chrePalWifiApiRequestScan,
190       .releaseScanEvent = chrePalWifiApiReleaseScanEvent,
191       .requestRanging = chrePalWifiApiRequestRanging,
192       .releaseRangingEvent = chrePalWifiApiReleaseRangingEvent,
193       .nanSubscribe = chrePalWifiApiNanSubscribe,
194       .nanSubscribeCancel = chrePalWifiApiNanSubscribeCancel,
195       .releaseNanDiscoveryEvent = chrePalWifiApiNanReleaseDiscoveryEvent,
196       .requestNanRanging = chrePalWifiApiRequestNanRanging,
197   };
198 
199   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
200                                         requestedApiVersion)) {
201     return nullptr;
202   } else {
203     chre::PalNanEngineSingleton::init();
204     return &kApi;
205   }
206 }
207