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