Roshan Pius | e65edb1 | 2016-11-22 13:02:01 -0800 | [diff] [blame] | 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 | |
| 17 | #include <android-base/logging.h> |
| 18 | #include <utils/SystemClock.h> |
| 19 | |
| 20 | #include "hidl_struct_util.h" |
| 21 | |
| 22 | namespace android { |
| 23 | namespace hardware { |
| 24 | namespace wifi { |
| 25 | namespace V1_0 { |
| 26 | namespace implementation { |
| 27 | namespace hidl_struct_util { |
| 28 | |
| 29 | uint8_t ConvertHidlReportEventFlagToLegacy( |
| 30 | StaBackgroundScanBucketEventReportSchemeMask hidl_flag) { |
| 31 | using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; |
| 32 | switch (hidl_flag) { |
| 33 | case HidlFlag::EACH_SCAN: |
| 34 | return REPORT_EVENTS_EACH_SCAN; |
| 35 | case HidlFlag::FULL_RESULTS: |
| 36 | return REPORT_EVENTS_FULL_RESULTS; |
| 37 | case HidlFlag::NO_BATCH: |
| 38 | return REPORT_EVENTS_NO_BATCH; |
| 39 | }; |
| 40 | } |
| 41 | |
| 42 | bool convertHidlScanParamsToLegacy( |
| 43 | const StaBackgroundScanParameters& hidl_scan_params, |
| 44 | legacy_hal::wifi_scan_cmd_params* legacy_scan_params) { |
| 45 | if (!legacy_scan_params) { |
| 46 | return false; |
| 47 | } |
| 48 | legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs; |
| 49 | legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan; |
| 50 | legacy_scan_params->report_threshold_percent = |
| 51 | hidl_scan_params.reportThresholdPercent; |
| 52 | legacy_scan_params->report_threshold_num_scans = |
| 53 | hidl_scan_params.reportThresholdNumScans; |
| 54 | // TODO(b/33194311): Expose these max limits in the HIDL interface. |
| 55 | if (hidl_scan_params.buckets.size() > MAX_BUCKETS) { |
| 56 | return false; |
| 57 | } |
| 58 | legacy_scan_params->num_buckets = hidl_scan_params.buckets.size(); |
| 59 | for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); |
| 60 | bucket_idx++) { |
| 61 | const StaBackgroundScanBucketParameters& hidl_bucket_spec = |
| 62 | hidl_scan_params.buckets[bucket_idx]; |
| 63 | legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec = |
| 64 | legacy_scan_params->buckets[bucket_idx]; |
| 65 | legacy_bucket_spec.bucket = bucket_idx; |
| 66 | legacy_bucket_spec.band = |
| 67 | static_cast<legacy_hal::wifi_band>(hidl_bucket_spec.band); |
| 68 | legacy_bucket_spec.period = hidl_bucket_spec.periodInMs; |
| 69 | legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs; |
| 70 | legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase; |
| 71 | legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount; |
| 72 | legacy_bucket_spec.report_events = 0; |
| 73 | using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; |
| 74 | for (const auto flag : |
| 75 | {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) { |
| 76 | if (hidl_bucket_spec.eventReportScheme & |
| 77 | static_cast<std::underlying_type<HidlFlag>::type>(flag)) { |
| 78 | legacy_bucket_spec.report_events |= |
| 79 | ConvertHidlReportEventFlagToLegacy(flag); |
| 80 | } |
| 81 | } |
| 82 | // TODO(b/33194311): Expose these max limits in the HIDL interface. |
| 83 | if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) { |
| 84 | return false; |
| 85 | } |
| 86 | legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size(); |
| 87 | for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size(); |
| 88 | freq_idx++) { |
| 89 | legacy_bucket_spec.channels[freq_idx].channel = |
| 90 | hidl_bucket_spec.frequencies[freq_idx]; |
| 91 | } |
| 92 | } |
| 93 | return true; |
| 94 | } |
| 95 | |
| 96 | bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, |
| 97 | uint32_t ie_blob_len, |
| 98 | std::vector<WifiInformationElement>* hidl_ies) { |
| 99 | if (!ie_blob || !hidl_ies) { |
| 100 | return false; |
| 101 | } |
| 102 | const uint8_t* ies_begin = ie_blob; |
| 103 | const uint8_t* ies_end = ie_blob + ie_blob_len; |
| 104 | const uint8_t* next_ie = ies_begin; |
| 105 | using wifi_ie = legacy_hal::wifi_information_element; |
| 106 | constexpr size_t kIeHeaderLen = sizeof(wifi_ie); |
| 107 | // Each IE should atleast have the header (i.e |id| & |len| fields). |
| 108 | while (next_ie + kIeHeaderLen <= ies_end) { |
| 109 | const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie)); |
| 110 | uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len; |
| 111 | if (next_ie + curr_ie_len > ies_end) { |
| 112 | return false; |
| 113 | } |
| 114 | WifiInformationElement hidl_ie; |
| 115 | hidl_ie.id = legacy_ie.id; |
| 116 | hidl_ie.data = |
| 117 | std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len); |
| 118 | hidl_ies->push_back(std::move(hidl_ie)); |
| 119 | next_ie += curr_ie_len; |
| 120 | } |
| 121 | // Ensure that the blob has been fully consumed. |
| 122 | return (next_ie == ies_end); |
| 123 | } |
| 124 | |
| 125 | bool convertLegacyScanResultToHidl( |
| 126 | const legacy_hal::wifi_scan_result& legacy_scan_result, |
| 127 | bool has_ie_data, |
| 128 | StaScanResult* hidl_scan_result) { |
| 129 | if (!hidl_scan_result) { |
| 130 | return false; |
| 131 | } |
| 132 | hidl_scan_result->timeStampInUs = legacy_scan_result.ts; |
| 133 | hidl_scan_result->ssid = std::vector<uint8_t>( |
| 134 | legacy_scan_result.ssid, |
| 135 | legacy_scan_result.ssid + sizeof(legacy_scan_result.ssid)); |
| 136 | memcpy(hidl_scan_result->bssid.data(), |
| 137 | legacy_scan_result.bssid, |
| 138 | hidl_scan_result->bssid.size()); |
| 139 | hidl_scan_result->frequency = legacy_scan_result.channel; |
| 140 | hidl_scan_result->rssi = legacy_scan_result.rssi; |
| 141 | hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period; |
| 142 | hidl_scan_result->capability = legacy_scan_result.capability; |
| 143 | if (has_ie_data) { |
| 144 | std::vector<WifiInformationElement> ies; |
| 145 | if (!convertLegacyIeBlobToHidl( |
| 146 | reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data), |
| 147 | legacy_scan_result.ie_length, |
| 148 | &ies)) { |
| 149 | return false; |
| 150 | } |
| 151 | hidl_scan_result->informationElements = std::move(ies); |
| 152 | } |
| 153 | return true; |
| 154 | } |
| 155 | |
| 156 | bool convertLegacyCachedScanResultsToHidl( |
| 157 | const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result, |
| 158 | StaScanData* hidl_scan_data) { |
| 159 | if (!hidl_scan_data) { |
| 160 | return false; |
| 161 | } |
| 162 | hidl_scan_data->flags = legacy_cached_scan_result.flags; |
| 163 | hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned; |
| 164 | |
| 165 | CHECK(legacy_cached_scan_result.num_results >= 0 && |
| 166 | legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN); |
| 167 | std::vector<StaScanResult> hidl_scan_results; |
| 168 | for (int32_t result_idx = 0; |
| 169 | result_idx < legacy_cached_scan_result.num_results; |
| 170 | result_idx++) { |
| 171 | StaScanResult hidl_scan_result; |
| 172 | if (!convertLegacyScanResultToHidl( |
| 173 | legacy_cached_scan_result.results[result_idx], |
| 174 | false, |
| 175 | &hidl_scan_result)) { |
| 176 | return false; |
| 177 | } |
| 178 | hidl_scan_results.push_back(hidl_scan_result); |
| 179 | } |
| 180 | hidl_scan_data->results = std::move(hidl_scan_results); |
| 181 | return true; |
| 182 | } |
| 183 | |
| 184 | bool convertLegacyVectorOfCachedScanResultsToHidl( |
| 185 | const std::vector<legacy_hal::wifi_cached_scan_results>& |
| 186 | legacy_cached_scan_results, |
| 187 | std::vector<StaScanData>* hidl_scan_datas) { |
| 188 | if (!hidl_scan_datas) { |
| 189 | return false; |
| 190 | } |
| 191 | for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) { |
| 192 | StaScanData hidl_scan_data; |
| 193 | if (!convertLegacyCachedScanResultsToHidl(legacy_cached_scan_result, |
| 194 | &hidl_scan_data)) { |
| 195 | return false; |
| 196 | } |
| 197 | hidl_scan_datas->push_back(hidl_scan_data); |
| 198 | } |
| 199 | return true; |
| 200 | } |
| 201 | |
| 202 | bool convertLegacyLinkLayerStatsToHidl( |
| 203 | const legacy_hal::LinkLayerStats& legacy_stats, |
| 204 | StaLinkLayerStats* hidl_stats) { |
| 205 | if (!hidl_stats) { |
| 206 | return false; |
| 207 | } |
| 208 | // iface legacy_stats conversion. |
| 209 | hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx; |
| 210 | hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; |
| 211 | hidl_stats->iface.wmeBePktStats.rxMpdu = |
| 212 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; |
| 213 | hidl_stats->iface.wmeBePktStats.txMpdu = |
| 214 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; |
| 215 | hidl_stats->iface.wmeBePktStats.lostMpdu = |
| 216 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; |
| 217 | hidl_stats->iface.wmeBePktStats.retries = |
| 218 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; |
| 219 | hidl_stats->iface.wmeBkPktStats.rxMpdu = |
| 220 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; |
| 221 | hidl_stats->iface.wmeBkPktStats.txMpdu = |
| 222 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; |
| 223 | hidl_stats->iface.wmeBkPktStats.lostMpdu = |
| 224 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; |
| 225 | hidl_stats->iface.wmeBkPktStats.retries = |
| 226 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; |
| 227 | hidl_stats->iface.wmeViPktStats.rxMpdu = |
| 228 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; |
| 229 | hidl_stats->iface.wmeViPktStats.txMpdu = |
| 230 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; |
| 231 | hidl_stats->iface.wmeViPktStats.lostMpdu = |
| 232 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; |
| 233 | hidl_stats->iface.wmeViPktStats.retries = |
| 234 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; |
| 235 | hidl_stats->iface.wmeVoPktStats.rxMpdu = |
| 236 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; |
| 237 | hidl_stats->iface.wmeVoPktStats.txMpdu = |
| 238 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; |
| 239 | hidl_stats->iface.wmeVoPktStats.lostMpdu = |
| 240 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; |
| 241 | hidl_stats->iface.wmeVoPktStats.retries = |
| 242 | legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; |
| 243 | // radio legacy_stats conversion. |
| 244 | hidl_stats->radio.onTimeInMs = legacy_stats.radio.on_time; |
| 245 | hidl_stats->radio.txTimeInMs = legacy_stats.radio.tx_time; |
| 246 | hidl_stats->radio.rxTimeInMs = legacy_stats.radio.rx_time; |
| 247 | hidl_stats->radio.onTimeInMsForScan = legacy_stats.radio.on_time_scan; |
| 248 | hidl_stats->radio.txTimeInMsPerLevel = legacy_stats.radio_tx_time_per_levels; |
| 249 | // Timestamp in the HAL wrapper here since it's not provided in the legacy |
| 250 | // HAL API. |
| 251 | hidl_stats->timeStampInMs = uptimeMillis(); |
| 252 | return true; |
| 253 | } |
| 254 | } // namespace hidl_struct_util |
| 255 | } // namespace implementation |
| 256 | } // namespace V1_0 |
| 257 | } // namespace wifi |
| 258 | } // namespace hardware |
| 259 | } // namespace android |