1 #include "offload_server.h"
2
3 #include <android-base/logging.h>
4 #include <chre/apps/wifi_offload/flatbuffers_serialization.h>
5 #include <chre/apps/wifi_offload/host_message_types.h>
6
7 #include "offload_status_util.h"
8 #include "offload_utils.h"
9
10 using namespace android::hardware::wifi::offload::V1_0::implementation::chre_constants;
11 using android::hardware::wifi::offload::V1_0::OffloadStatus;
12
13 namespace {
14 constexpr auto kScanStatsTimeout = std::chrono::milliseconds(500);
15 }
16
17 namespace android {
18 namespace hardware {
19 namespace wifi {
20 namespace offload {
21 namespace V1_0 {
22 namespace implementation {
23
24 class OffloadServer;
25
OffloadServer(ChreInterfaceFactory * factory)26 OffloadServer::OffloadServer(ChreInterfaceFactory* factory)
27 : mChreInterfaceCallbacks(new ChreInterfaceCallbacksImpl(this)),
28 mChreInterface(factory->getChreInterface(mChreInterfaceCallbacks.get())) {
29 LOG(VERBOSE) << "Wifi Offload HAL impl";
30 }
31
configureScans(const ScanParam & param,const ScanFilter & filter)32 OffloadStatus OffloadServer::configureScans(const ScanParam& param, const ScanFilter& filter) {
33 LOG(INFO) << "configureScans";
34 if (!mChreInterface->isConnected()) {
35 return createOffloadStatus(OffloadStatusCode::NO_CONNECTION,
36 "Not connected to hardware implementation");
37 }
38 wifi_offload::ScanConfig scanConfig;
39 if (!offload_utils::ToChreScanConfig(param, filter, &scanConfig)) {
40 return createOffloadStatus(OffloadStatusCode::ERROR,
41 "Unable to convert scan configuration");
42 }
43 uint8_t buffer[kMaxMessageLen];
44 size_t result_size = wifi_offload::fbs::Serialize(scanConfig, buffer, kMaxMessageLen);
45 if (result_size <= 0) {
46 return createOffloadStatus(OffloadStatusCode::ERROR, "Scan config serialization failed");
47 }
48 std::vector<uint8_t> message(buffer, buffer + result_size);
49 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_CONFIG_SCANS,
50 message)) {
51 return createOffloadStatus(OffloadStatusCode::ERROR, "Unable to send config message");
52 }
53 return createOffloadStatus(OffloadStatusCode::OK);
54 }
55
getScanStats()56 std::pair<OffloadStatus, ScanStats> OffloadServer::getScanStats() {
57 LOG(INFO) << "getScanStats";
58 mScanStatsStatus = createOffloadStatus(OffloadStatusCode::OK);
59 if (!mChreInterface->isConnected()) {
60 return {createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Unable to send scan stats"),
61 {}};
62 }
63 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_GET_SCAN_STATS,
64 {})) {
65 return {createOffloadStatus(OffloadStatusCode::ERROR, "Unable to send scan stats command"),
66 {}};
67 }
68 LOG(VERBOSE) << "Sent getScanStats command";
69 {
70 std::unique_lock<std::mutex> lock(mScanStatsLock);
71 auto timeout_status = mScanStatsCond.wait_for(lock, kScanStatsTimeout);
72 if (timeout_status == std::cv_status::timeout) {
73 std::lock_guard<std::mutex> lock(mOffloadLock);
74 LOG(WARNING) << "Timeout waiting for scan stats";
75 return {createOffloadStatus(OffloadStatusCode::TIMEOUT, "Scan stats not received"), {}};
76 }
77 }
78 return std::make_pair(mScanStatsStatus, mScanStats);
79 }
80
subscribeScanResults(uint32_t delayMs)81 OffloadStatus OffloadServer::subscribeScanResults(uint32_t delayMs) {
82 LOG(INFO) << "subscribeScanResults with delay:" << delayMs;
83 if (!mChreInterface->isConnected()) {
84 return createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Not connected to hardware");
85 }
86 uint32_t* buffer = &delayMs;
87 std::vector<uint8_t> message(reinterpret_cast<uint8_t*>(buffer),
88 reinterpret_cast<uint8_t*>(buffer) + kSubscriptionDelayMsBufLen);
89 if (!mChreInterface->sendCommandToApp(
90 wifi_offload::HostMessageType::HOST_CMD_SUBSCRIBE_SCAN_RESULTS, message)) {
91 return createOffloadStatus(OffloadStatusCode::ERROR, "Unable to request scans");
92 }
93 return createOffloadStatus(OffloadStatusCode::OK);
94 }
95
resetNanoApp()96 void OffloadServer::resetNanoApp() {
97 LOG(INFO) << "resetting Nano app";
98 if (!mChreInterface->isConnected()) {
99 LOG(WARNING) << "Unable to reset nano app, not connected";
100 return;
101 }
102 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_RESET, {})) {
103 LOG(ERROR) << "Unable to send Reset command to Nano app";
104 }
105 }
106
unsubscribeScanResults()107 bool OffloadServer::unsubscribeScanResults() {
108 LOG(INFO) << "unsubscribeScanResults";
109 if (!mChreInterface->isConnected()) {
110 LOG(WARNING) << "Failed to send unsubscribe scan results message";
111 return false;
112 }
113 if (!mChreInterface->sendCommandToApp(
114 wifi_offload::HostMessageType::HOST_CMD_UNSUBSCRIBE_SCAN_RESULTS, {})) {
115 LOG(WARNING) << "Failed to send unsubscribe scan results message";
116 return false;
117 }
118 return true;
119 }
120
setEventCallback(const sp<IOffloadCallback> & cb)121 bool OffloadServer::setEventCallback(const sp<IOffloadCallback>& cb) {
122 LOG(INFO) << "Set Event callback";
123 if (cb == nullptr) {
124 return false;
125 }
126 std::lock_guard<std::mutex> lock(mOffloadLock);
127 mEventCallback = cb;
128 return true;
129 }
130
clearEventCallback()131 void OffloadServer::clearEventCallback() {
132 std::lock_guard<std::mutex> lock(mOffloadLock);
133 if (mEventCallback != nullptr) {
134 mEventCallback.clear();
135 }
136 LOG(INFO) << "Event callback cleared";
137 }
138
invokeErrorCallbackAndResetIfNeeded(const OffloadStatus & status)139 void OffloadServer::invokeErrorCallbackAndResetIfNeeded(const OffloadStatus& status) {
140 if (status.code != OffloadStatusCode::OK) {
141 resetNanoApp();
142 }
143 std::lock_guard<std::mutex> lock(mOffloadLock);
144 if (mEventCallback != nullptr) {
145 mEventCallback->onError(status);
146 }
147 }
148
ChreInterfaceCallbacksImpl(OffloadServer * server)149 ChreInterfaceCallbacksImpl::ChreInterfaceCallbacksImpl(OffloadServer* server) : mServer(server) {
150 }
151
~ChreInterfaceCallbacksImpl()152 ChreInterfaceCallbacksImpl::~ChreInterfaceCallbacksImpl() {
153 }
154
handleConnectionEvents(ChreInterfaceCallbacks::ConnectionEvent event)155 void ChreInterfaceCallbacksImpl::handleConnectionEvents(
156 ChreInterfaceCallbacks::ConnectionEvent event) {
157 switch (event) {
158 case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED:
159 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: {
160 LOG(ERROR) << "Connection to socket lost";
161 mServer->invokeErrorCallbackAndResetIfNeeded(
162 createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Connection to socket lost"));
163 } break;
164 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: {
165 LOG(INFO) << "Connected to socket";
166 mServer->invokeErrorCallbackAndResetIfNeeded(
167 createOffloadStatus(OffloadStatusCode::OK));
168 } break;
169 default:
170 LOG(WARNING) << "Invalid connection event received " << (int)event;
171 break;
172 }
173 }
174
handleScanResult(const std::vector<uint8_t> & message)175 void OffloadServer::handleScanResult(const std::vector<uint8_t>& message) {
176 std::vector<wifi_offload::ScanResult> scanResults;
177 std::vector<ScanResult> hidlScanResults;
178 std::string errorMessage;
179 if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &scanResults)) {
180 invokeErrorCallbackAndResetIfNeeded(
181 createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserialize scan results"));
182 return;
183 }
184 if (!offload_utils::ToHidlScanResults(scanResults, &hidlScanResults)) {
185 invokeErrorCallbackAndResetIfNeeded(createOffloadStatus(
186 OffloadStatusCode::ERROR, "Cannot convert scan results to HIDL format"));
187 return;
188 }
189 {
190 std::lock_guard<std::mutex> lock(mOffloadLock);
191 if (mEventCallback != nullptr) {
192 mEventCallback->onScanResult(hidlScanResults);
193 }
194 }
195 }
196
handleScanStats(const std::vector<uint8_t> & message)197 void OffloadServer::handleScanStats(const std::vector<uint8_t>& message) {
198 std::lock_guard<std::mutex> lock(mScanStatsLock);
199 wifi_offload::ScanStats stats;
200 OffloadStatus status;
201 // Deserialize scan stats
202 status = createOffloadStatus(OffloadStatusCode::OK);
203 LOG(VERBOSE) << "Received scan stats";
204 if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &stats)) {
205 status = createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserailize scan stats");
206 } else if (!offload_utils::ToHidlScanStats(stats, &mScanStats)) {
207 status = createOffloadStatus(OffloadStatusCode::ERROR,
208 "Cannot convert Scan stats to HIDL format");
209 }
210 mScanStatsStatus = status;
211 mScanStatsCond.notify_all();
212 }
213
handleMessage(uint32_t messageType,const std::vector<uint8_t> & message)214 void ChreInterfaceCallbacksImpl::handleMessage(uint32_t messageType,
215 const std::vector<uint8_t>& message) {
216 LOG(VERBOSE) << "Message from Nano app " << messageType;
217 switch (messageType) {
218 case wifi_offload::HostMessageType::HOST_MSG_SCAN_RESULTS: {
219 LOG(INFO) << "Received scan results";
220 mServer->handleScanResult(message);
221 } break;
222 case wifi_offload::HostMessageType::HOST_MSG_SCAN_STATS:
223 LOG(VERBOSE) << "Received scan stats from Nano app";
224 mServer->handleScanStats(message);
225 break;
226 case wifi_offload::HostMessageType::HOST_MSG_ERROR:
227 LOG(VERBOSE) << "Received error message from Nano app";
228 {
229 std::string errorMessage;
230 if (offload_utils::ToHidlErrorMessage(message[0], &errorMessage)) {
231 mServer->invokeErrorCallbackAndResetIfNeeded(
232 createOffloadStatus(OffloadStatusCode::ERROR, errorMessage));
233 }
234 }
235 break;
236 default:
237 LOG(WARNING) << "Unknown message received" << messageType;
238 break;
239 }
240 }
241
242 // Methods from ::android::hidl::base::V1_0::IBase follow.
243
244 } // namespace implementation
245 } // namespace V1_0
246 } // namespace offload
247 } // namespace wifi
248 } // namespace hardware
249 } // namespace android
250