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 <chrono>
23 #include <cinttypes>
24 #include <thread>
25 
26 /**
27  * A simulated implementation of the WiFi PAL for the linux platform.
28  */
29 namespace {
30 const struct chrePalSystemApi *gSystemApi = nullptr;
31 const struct chrePalWifiCallbacks *gCallbacks = nullptr;
32 
33 //! Thread to deliver asynchronous WiFi scan results after a CHRE request.
34 std::thread gScanEventsThread;
35 
36 //! Thread to use when delivering a scan monitor status update.
37 std::thread gScanMonitorStatusThread;
38 
sendScanResponse()39 void sendScanResponse() {
40   gCallbacks->scanResponseCallback(true, CHRE_ERROR_NONE);
41 
42   auto event = chre::MakeUniqueZeroFill<struct chreWifiScanEvent>();
43   auto result = chre::MakeUniqueZeroFill<struct chreWifiScanResult>();
44   event->resultCount = 1;
45   event->resultTotal = 1;
46   event->referenceTime = gSystemApi->getCurrentTime();
47   event->results = result.release();
48 
49   gCallbacks->scanEventCallback(event.release());
50 }
51 
sendScanMonitorResponse(bool enable)52 void sendScanMonitorResponse(bool enable) {
53   gCallbacks->scanMonitorStatusChangeCallback(enable, CHRE_ERROR_NONE);
54 }
55 
stopScanEventThreads()56 void stopScanEventThreads() {
57   if (gScanEventsThread.joinable()) {
58     gScanEventsThread.join();
59   }
60 }
61 
stopScanMonitorThreads()62 void stopScanMonitorThreads() {
63   if (gScanMonitorStatusThread.joinable()) {
64     gScanMonitorStatusThread.join();
65   }
66 }
67 
chrePalWifiGetCapabilities()68 uint32_t chrePalWifiGetCapabilities() {
69   return CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
70          CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN;
71 }
72 
chrePalWifiConfigureScanMonitor(bool enable)73 bool chrePalWifiConfigureScanMonitor(bool enable) {
74   stopScanMonitorThreads();
75 
76   gScanMonitorStatusThread = std::thread(sendScanMonitorResponse, enable);
77 
78   return true;
79 }
80 
chrePalWifiApiRequestScan(const struct chreWifiScanParams *)81 bool chrePalWifiApiRequestScan(const struct chreWifiScanParams * /* params */) {
82   stopScanEventThreads();
83 
84   gScanEventsThread = std::thread(sendScanResponse);
85 
86   return true;
87 }
88 
chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent * event)89 void chrePalWifiApiReleaseScanEvent(struct chreWifiScanEvent *event) {
90   chre::memoryFree(const_cast<uint32_t *>(event->scannedFreqList));
91   chre::memoryFree(const_cast<struct chreWifiScanResult *>(event->results));
92   chre::memoryFree(event);
93 }
94 
chrePalWifiApiClose()95 void chrePalWifiApiClose() {
96   stopScanEventThreads();
97   stopScanMonitorThreads();
98 }
99 
chrePalWifiApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWifiCallbacks * callbacks)100 bool chrePalWifiApiOpen(const struct chrePalSystemApi *systemApi,
101                         const struct chrePalWifiCallbacks *callbacks) {
102   chrePalWifiApiClose();
103 
104   bool success = false;
105   if (systemApi != nullptr && callbacks != nullptr) {
106     gSystemApi = systemApi;
107     gCallbacks = callbacks;
108     success = true;
109   }
110 
111   return success;
112 }
113 
114 }  // anonymous namespace
115 
chrePalWifiGetApi(uint32_t requestedApiVersion)116 const struct chrePalWifiApi *chrePalWifiGetApi(uint32_t requestedApiVersion) {
117   static const struct chrePalWifiApi kApi = {
118       .moduleVersion = CHRE_PAL_WIFI_API_CURRENT_VERSION,
119       .open = chrePalWifiApiOpen,
120       .close = chrePalWifiApiClose,
121       .getCapabilities = chrePalWifiGetCapabilities,
122       .configureScanMonitor = chrePalWifiConfigureScanMonitor,
123       .requestScan = chrePalWifiApiRequestScan,
124       .releaseScanEvent = chrePalWifiApiReleaseScanEvent,
125   };
126 
127   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
128                                         requestedApiVersion)) {
129     return nullptr;
130   } else {
131     return &kApi;
132   }
133 }
134