You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
5.4 KiB
172 lines
5.4 KiB
/* |
|
* Copyright (C) 2017 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include "chre/apps/wifi_offload/channel_histogram.h" |
|
#include "chre/apps/wifi_offload/utility.h" |
|
|
|
namespace wifi_offload { |
|
namespace { |
|
|
|
/* Strictly increasing sequence of supported channel numbers in |
|
* 2.4GHz (802.11b/g/n) and 5GHz (802.11a/h/j/n/ac) */ |
|
constexpr uint8_t kAllChannels[] = { |
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|
16, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, |
|
60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, |
|
122, 124, 126, 128, 132, 134, 136, 138, 140, 142, 144, 149, 151, 153, |
|
155, 157, 159, 161, 165, 183, 184, 185, 187, 188, 189, 192, 196, |
|
}; |
|
static_assert(sizeof(kAllChannels) / sizeof(kAllChannels[0]) == |
|
ChannelHistogram::kNumChannels, |
|
"some elements unspecified"); |
|
|
|
/** |
|
* Returns the channel number of a given frequency based on 802.11. |
|
* |
|
* @param frequency Frequncy of the channel in MHz |
|
* |
|
* @return Channel number of the given frequency. Zero if unsupported |
|
* frequency or channel number. Returned value will be in the range of |
|
* [0, 255] |
|
*/ |
|
uint8_t GetChannelNumber(uint32_t frequency) { |
|
int channel_number = |
|
utility::Ieee80211FrequencyToChannel(static_cast<int>(frequency)); |
|
if (channel_number <= 0 || channel_number > 255) { |
|
LOGE("Unknown channel frequency %" PRIu32 " MHz.", frequency); |
|
channel_number = 0; |
|
} |
|
return static_cast<uint8_t>(channel_number); |
|
} |
|
|
|
/** |
|
* Returns the index of a given channel number in kAllChannels. |
|
* |
|
* @param channel_number Channel number we want to map to an index |
|
* |
|
* @return Index of the given channel number in kAllChannels. kNumChannels if |
|
* not found. Returned value will be in the range of [0, kNumChannels] |
|
*/ |
|
size_t GetChannelIndex(uint8_t channel_number) { |
|
for (size_t i = 0; i < ChannelHistogram::kNumChannels; i++) { |
|
if (channel_number == kAllChannels[i]) { |
|
return i; |
|
} |
|
} |
|
|
|
LOGE("Unsupported channel number: %" PRIu8, channel_number); |
|
return ChannelHistogram::kNumChannels; |
|
} |
|
|
|
} // namespace |
|
|
|
ChannelHistogram::ChannelHistogram() { |
|
std::memset(scan_count_internal_high_res_, 0, |
|
sizeof(scan_count_internal_high_res_)); |
|
} |
|
|
|
bool ChannelHistogram::IsSupportedFrequency(uint32_t frequency) { |
|
return GetChannelNumber(frequency) != 0; |
|
} |
|
|
|
uint8_t ChannelHistogram::GetChannelScanCount(uint8_t channel_number) const { |
|
size_t index = GetChannelIndex(channel_number); |
|
if (index == kNumChannels) { |
|
return 0; |
|
} |
|
|
|
if (scan_count_internal_high_res_[index] == 0) { |
|
return 0; |
|
} |
|
|
|
uint32_t max_count = 0; |
|
// since there is at least one non-zero value, max_count won't be 0 |
|
for (const auto count : scan_count_internal_high_res_) { |
|
if (max_count < count) { |
|
max_count = count; |
|
} |
|
} |
|
|
|
// linearly map from [1,max_count] to [1,255] |
|
uint64_t scaled_value = scan_count_internal_high_res_[index]; |
|
scaled_value = scaled_value * 254 / max_count + 1; |
|
return static_cast<uint8_t>(scaled_value); |
|
} |
|
|
|
bool ChannelHistogram::IncrementScanCountForFrequency(uint32_t frequency) { |
|
size_t index = GetChannelIndex(GetChannelNumber(frequency)); |
|
if (index == kNumChannels) { |
|
return false; |
|
} |
|
|
|
scan_count_internal_high_res_[index]++; |
|
return true; |
|
} |
|
|
|
bool ChannelHistogram::IncrementScanCountForFrequencyForTest( |
|
uint32_t frequency, uint32_t increase_count) { |
|
return IncrementScanCountForChannelForTest(GetChannelNumber(frequency), |
|
increase_count); |
|
} |
|
|
|
bool ChannelHistogram::IncrementScanCountForChannelForTest( |
|
uint8_t channel, uint32_t increase_count) { |
|
size_t index = GetChannelIndex(channel); |
|
if (index == kNumChannels) { |
|
return false; |
|
} |
|
|
|
scan_count_internal_high_res_[index] += increase_count; |
|
return true; |
|
} |
|
|
|
bool ChannelHistogram::operator==(const ChannelHistogram &other) const { |
|
if (this == &other) { |
|
return true; |
|
} |
|
|
|
for (const auto channel : kAllChannels) { |
|
// Compare scaled values, rather than raw values |
|
if (GetChannelScanCount(channel) != other.GetChannelScanCount(channel)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> ChannelHistogram::Serialize( |
|
flatbuffers::FlatBufferBuilder *builder) const { |
|
uint8_t lowResScanCount[kNumChannels]; |
|
for (size_t i = 0; i < kNumChannels; i++) { |
|
lowResScanCount[i] = GetChannelScanCount(kAllChannels[i]); |
|
} |
|
return builder->CreateVector(lowResScanCount, kNumChannels); |
|
} |
|
|
|
bool ChannelHistogram::Deserialize( |
|
const flatbuffers::Vector<uint8_t> &fbs_scan_count) { |
|
if (fbs_scan_count.size() != kNumChannels) { |
|
LOGE("Failed to deserialize ChannelHistogram. Null or incomplete members."); |
|
return false; |
|
} |
|
|
|
for (uint8_t i = 0; i < kNumChannels; i++) { |
|
scan_count_internal_high_res_[i] = fbs_scan_count.Get(i); |
|
} |
|
return true; |
|
} |
|
|
|
} // namespace wifi_offload
|
|
|