• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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