Home | History | Annotate | Download | only in wifi_offload
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    149 ChreInterfaceCallbacksImpl::ChreInterfaceCallbacksImpl(OffloadServer* server) : mServer(server) {
    150 }
    151 
    152 ChreInterfaceCallbacksImpl::~ChreInterfaceCallbacksImpl() {
    153 }
    154 
    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 
    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 
    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 
    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