Home | History | Annotate | Download | only in offload
      1 /*
      2  * Copyright (C) 2016 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 #include "wificond/scanning/offload/offload_scan_manager.h"
     17 
     18 #include <vector>
     19 
     20 #include <android-base/logging.h>
     21 
     22 #include "wificond/scanning/offload/hidl_call_util.h"
     23 #include "wificond/scanning/offload/offload_scan_utils.h"
     24 #include "wificond/scanning/offload/offload_service_utils.h"
     25 #include "wificond/scanning/offload/scan_stats.h"
     26 #include "wificond/scanning/scan_result.h"
     27 
     28 using ::android::hardware::hidl_vec;
     29 using android::hardware::wifi::offload::V1_0::IOffload;
     30 using android::hardware::wifi::offload::V1_0::ScanResult;
     31 using android::hardware::wifi::offload::V1_0::ScanFilter;
     32 using android::hardware::wifi::offload::V1_0::ScanParam;
     33 using android::hardware::wifi::offload::V1_0::ScanStats;
     34 using android::hardware::wifi::offload::V1_0::OffloadStatus;
     35 using android::hardware::wifi::offload::V1_0::OffloadStatusCode;
     36 
     37 using android::wificond::OffloadCallback;
     38 using ::com::android::server::wifi::wificond::NativeScanResult;
     39 using ::com::android::server::wifi::wificond::NativeScanStats;
     40 using std::vector;
     41 using std::weak_ptr;
     42 using std::shared_ptr;
     43 
     44 using namespace std::placeholders;
     45 
     46 namespace {
     47 const uint32_t kSubscriptionDelayMs = 5000;
     48 }
     49 
     50 namespace android {
     51 namespace wificond {
     52 
     53 OffloadCallbackHandlersImpl::OffloadCallbackHandlersImpl(
     54     OffloadScanManager* offload_scan_manager)
     55     : offload_scan_manager_(offload_scan_manager) {}
     56 
     57 OffloadCallbackHandlersImpl::~OffloadCallbackHandlersImpl() {}
     58 
     59 void OffloadCallbackHandlersImpl::OnScanResultHandler(
     60     const vector<ScanResult>& scanResult) {
     61   if (offload_scan_manager_ != nullptr) {
     62     offload_scan_manager_->ReportScanResults(scanResult);
     63   }
     64 }
     65 
     66 void OffloadCallbackHandlersImpl::OnErrorHandler(const OffloadStatus& status) {
     67   if (offload_scan_manager_ != nullptr) {
     68     offload_scan_manager_->ReportError(status);
     69   }
     70 }
     71 
     72 OffloadScanManager::OffloadScanManager(
     73     weak_ptr<OffloadServiceUtils> utils,
     74     shared_ptr<OffloadScanCallbackInterface> callback)
     75     : wifi_offload_hal_(nullptr),
     76       wifi_offload_callback_(nullptr),
     77       death_recipient_(nullptr),
     78       offload_status_(OffloadScanManager::kError),
     79       service_available_(false),
     80       offload_service_utils_(utils),
     81       offload_callback_handlers_(new OffloadCallbackHandlersImpl(this)),
     82       event_callback_(callback) {
     83   if (InitService()) {
     84     offload_status_ = OffloadScanManager::kNoError;
     85   }
     86 }
     87 
     88 bool OffloadScanManager::InitService() {
     89   wifi_offload_hal_ = offload_service_utils_.lock()->GetOffloadService();
     90   if (wifi_offload_hal_ == nullptr) {
     91     LOG(ERROR) << "No Offload Service available";
     92     return false;
     93   }
     94 
     95   death_recipient_ = offload_service_utils_.lock()->GetOffloadDeathRecipient(
     96       std::bind(&OffloadScanManager::OnObjectDeath, this, _1));
     97   uint64_t cookie = reinterpret_cast<uint64_t>(wifi_offload_hal_.get());
     98 
     99   auto link_to_death_status =
    100       wifi_offload_hal_->linkToDeath(death_recipient_, cookie);
    101   if (!link_to_death_status.isOk()) {
    102     LOG(ERROR) << "Unable to register death handler "
    103                << link_to_death_status.description();
    104     return false;
    105   }
    106 
    107   wifi_offload_callback_ = offload_service_utils_.lock()->GetOffloadCallback(
    108       offload_callback_handlers_.get());
    109   if (wifi_offload_callback_ == nullptr) {
    110     LOG(ERROR) << "Invalid Offload callback object";
    111     return false;
    112   }
    113 
    114   auto set_callback_status =
    115       wifi_offload_hal_->setEventCallback(wifi_offload_callback_);
    116   if (!set_callback_status.isOk()) {
    117     LOG(ERROR) << "Unable to set event callback for Offload HAL";
    118     return false;
    119   }
    120 
    121   service_available_ = true;
    122   return true;
    123 }
    124 
    125 bool OffloadScanManager::InitServiceIfNeeded() {
    126   if (!service_available_) {
    127     return InitService();
    128   }
    129   return true;
    130 }
    131 
    132 bool OffloadScanManager::stopScan(OffloadScanManager::ReasonCode* reason_code) {
    133   if (!InitServiceIfNeeded() ||
    134       (getOffloadStatus() != OffloadScanManager::kNoError)) {
    135     *reason_code = OffloadScanManager::kNotAvailable;
    136     return false;
    137   }
    138   const auto& res = wifi_offload_hal_->unsubscribeScanResults();
    139   if (!res.isOk()) {
    140     *reason_code = OffloadScanManager::kTransactionFailed;
    141     LOG(WARNING) << "unsubscribeScanResults() failed " << res.description();
    142     return false;
    143   }
    144   *reason_code = OffloadScanManager::kNone;
    145   return true;
    146 }
    147 
    148 bool OffloadScanManager::GetScanStats(NativeScanStats* native_scan_stats) {
    149   const auto& result = HIDL_INVOKE(wifi_offload_hal_, getScanStats);
    150   const auto& offload_status_and_scan_stats = result.first;
    151   bool transport_status = result.second;
    152   if (!transport_status) {
    153     return false;
    154   }
    155   OffloadStatus offload_status = offload_status_and_scan_stats.first;
    156   ScanStats scan_stats = offload_status_and_scan_stats.second;
    157   if (offload_status.code != OffloadStatusCode::OK) {
    158     LOG(WARNING) << offload_status.description;
    159     return false;
    160   }
    161   *native_scan_stats = OffloadScanUtils::convertToNativeScanStats(scan_stats);
    162   return true;
    163 }
    164 
    165 bool OffloadScanManager::VerifyAndConvertHIDLStatus(
    166     std::pair<OffloadStatus, bool> result,
    167     OffloadScanManager::ReasonCode* reason_code) {
    168   const auto& offload_status = result.first;
    169   bool transport_status = result.second;
    170   if (!transport_status) {
    171     *reason_code = OffloadScanManager::kTransactionFailed;
    172     return false;
    173   }
    174   if (offload_status.code != OffloadStatusCode::OK) {
    175     LOG(WARNING) << offload_status.description;
    176     *reason_code = OffloadScanManager::kOperationFailed;
    177     return false;
    178   }
    179   return true;
    180 }
    181 
    182 bool OffloadScanManager::startScan(
    183     uint32_t interval_ms, int32_t rssi_threshold,
    184     const vector<vector<uint8_t>>& scan_ssids,
    185     const vector<vector<uint8_t>>& match_ssids,
    186     const vector<uint8_t>& match_security, const vector<uint32_t>& freqs,
    187     OffloadScanManager::ReasonCode* reason_code) {
    188   if (!InitServiceIfNeeded() ||
    189       getOffloadStatus() != OffloadScanManager::kNoError) {
    190     *reason_code = OffloadScanManager::kNotAvailable;
    191     LOG(WARNING) << "Offload HAL scans are not available";
    192     return false;
    193   }
    194   ScanParam param =
    195       OffloadScanUtils::createScanParam(scan_ssids, freqs, interval_ms);
    196   ScanFilter filter = OffloadScanUtils::createScanFilter(
    197       match_ssids, match_security, rssi_threshold);
    198 
    199   if (!ConfigureScans(param, filter, reason_code)) {
    200     return false;
    201   }
    202 
    203   if (!SubscribeScanResults(reason_code)) {
    204     return false;
    205   }
    206 
    207   *reason_code = OffloadScanManager::kNone;
    208   return true;
    209 }
    210 
    211 bool OffloadScanManager::ConfigureScans(
    212     ScanParam param, ScanFilter filter,
    213     OffloadScanManager::ReasonCode* reason_code) {
    214   const auto& result =
    215       HIDL_INVOKE(wifi_offload_hal_, configureScans, param, filter);
    216   if (!VerifyAndConvertHIDLStatus(result, reason_code)) {
    217     return false;
    218   }
    219   return true;
    220 }
    221 
    222 bool OffloadScanManager::SubscribeScanResults(
    223     OffloadScanManager::ReasonCode* reason_code) {
    224   const auto& result = HIDL_INVOKE(wifi_offload_hal_, subscribeScanResults,
    225                                    kSubscriptionDelayMs);
    226   if (!VerifyAndConvertHIDLStatus(result, reason_code)) {
    227     return false;
    228   }
    229   return true;
    230 }
    231 
    232 OffloadScanManager::StatusCode OffloadScanManager::getOffloadStatus() const {
    233   if (!service_available_) {
    234     return OffloadScanManager::kNoService;
    235   }
    236   return offload_status_;
    237 }
    238 
    239 bool OffloadScanManager::getScanResults(
    240     std::vector<NativeScanResult>* out_scan_results) {
    241   for (const auto& scan_result : cached_scan_results_) {
    242     out_scan_results->push_back(scan_result);
    243   }
    244   return true;
    245 }
    246 
    247 bool OffloadScanManager::getScanStats(NativeScanStats* native_scan_stats) {
    248   if (!InitServiceIfNeeded()) {
    249     LOG(ERROR) << "Offload HAL service unavailable";
    250     return false;
    251   }
    252   if (getOffloadStatus() != OffloadScanManager::kNoError) {
    253     LOG(WARNING) << "Unable to get scan stats due to Wifi Offload HAL error";
    254     return false;
    255   }
    256   return GetScanStats(native_scan_stats);
    257 }
    258 
    259 OffloadScanManager::~OffloadScanManager() {
    260   if (wifi_offload_hal_ != nullptr) {
    261     wifi_offload_hal_->unlinkToDeath(death_recipient_);
    262   }
    263 }
    264 
    265 void OffloadScanManager::ReportScanResults(
    266     const vector<ScanResult>& scanResult) {
    267   cached_scan_results_.clear();
    268   if (!OffloadScanUtils::convertToNativeScanResults(scanResult,
    269                                                     &cached_scan_results_)) {
    270     LOG(WARNING) << "Unable to convert scan results to native format";
    271     return;
    272   }
    273   if (event_callback_ != nullptr) {
    274     event_callback_->OnOffloadScanResult();
    275   } else {
    276     LOG(WARNING)
    277         << "No callback to report Offload HAL's scan results to wificond";
    278   }
    279 }
    280 
    281 void OffloadScanManager::ReportError(const OffloadStatus& status) {
    282   OffloadStatusCode status_code = status.code;
    283   OffloadScanManager::StatusCode status_result = OffloadScanManager::kNoError;
    284   switch (status_code) {
    285     case OffloadStatusCode::OK:
    286       status_result = OffloadScanManager::kNoError;
    287       break;
    288     case OffloadStatusCode::TIMEOUT:
    289       status_result = OffloadScanManager::kTimeOut;
    290       break;
    291     case OffloadStatusCode::NO_CONNECTION:
    292       status_result = OffloadScanManager::kNotConnected;
    293       break;
    294     case OffloadStatusCode::ERROR:
    295       status_result = OffloadScanManager::kError;
    296       break;
    297     default:
    298       LOG(WARNING) << "Invalid Offload Error reported";
    299       return;
    300   }
    301   if (status_result != OffloadScanManager::kNoError) {
    302     LOG(WARNING) << "Offload Error reported " << status.description;
    303     if (event_callback_ != nullptr) {
    304       event_callback_->OnOffloadError(
    305           OffloadScanCallbackInterface::REMOTE_FAILURE);
    306     } else {
    307       LOG(WARNING) << "No callback to report Offload HAL Errors to wificond";
    308     }
    309   }
    310   offload_status_ = status_result;
    311 }
    312 
    313 void OffloadScanManager::OnObjectDeath(uint64_t cookie) {
    314   if (wifi_offload_hal_ == reinterpret_cast<IOffload*>(cookie)) {
    315     LOG(ERROR) << "Death Notification for Wifi Offload HAL";
    316     wifi_offload_hal_.clear();
    317     if (event_callback_ != nullptr) {
    318       event_callback_->OnOffloadError(
    319           OffloadScanCallbackInterface::BINDER_DEATH);
    320     } else {
    321       LOG(WARNING)
    322           << "No callback to report Offload HAL Binder death to wificond";
    323     }
    324     service_available_ = false;
    325     death_recipient_.clear();
    326   }
    327 }
    328 
    329 }  // namespace wificond
    330 }  // namespace android
    331