Chromium Code Reviews| Index: components/data_usage/android/traffic_stats_amortizer.cc |
| diff --git a/components/data_usage/android/traffic_stats_amortizer.cc b/components/data_usage/android/traffic_stats_amortizer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..21b4552a88bec5dfba89be0cddd18aecc5c22833 |
| --- /dev/null |
| +++ b/components/data_usage/android/traffic_stats_amortizer.cc |
| @@ -0,0 +1,103 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "components/data_usage/android/traffic_stats_amortizer.h" |
| + |
| +#include <cmath> |
| + |
| +#include "net/android/traffic_stats.h" |
| + |
| +namespace data_usage { |
| +namespace android { |
| + |
| +namespace { |
| + |
| +int64_t AmortizeByRatio(int64_t bytes, double ratio, double* remainder) { |
|
tbansal1
2015/10/12 21:23:20
please add comments.
|
| + DCHECK(remainder); |
| + |
| + double intpart; |
|
tbansal1
2015/10/12 21:23:20
may be initialize to -1, than DCHECK_GE() below wo
|
| + *remainder = |
| + std::modf(static_cast<double>(bytes) * ratio + (*remainder), &intpart); |
| + |
| + DCHECK_GE(intpart, 0.0); |
| + DCHECK_LE(intpart, static_cast<double>(INT64_MAX)); |
| + return static_cast<int64_t>(intpart); |
| +} |
| + |
| +} // namespace |
| + |
| +TrafficStatsAmortizer::TrafficStatsAmortizer() |
| + : are_traffic_stats_available_(false), |
| + traffic_stats_tx_bytes_(0), |
| + traffic_stats_rx_bytes_(0) {} |
| + |
| +TrafficStatsAmortizer::~TrafficStatsAmortizer() {} |
| + |
| +void TrafficStatsAmortizer::Amortize(std::vector<DataUse>* data_use_sequence, |
| + int64_t extra_tx_bytes, |
| + int64_t extra_rx_bytes) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(!data_use_sequence->empty()); |
| + |
| + bool previous_are_traffic_stats_available = are_traffic_stats_available_; |
| + int64_t previous_traffic_stats_tx_bytes = traffic_stats_tx_bytes_; |
| + int64_t previous_traffic_stats_rx_bytes = traffic_stats_rx_bytes_; |
| + |
| + // TODO(sclittle): Currently, the TrafficStats numbers don't seem to update |
| + // fast enough for the amortization to be accurate at this frequency. Find |
| + // some way to smooth out these numbers nicely, e.g. amortize over a longer |
| + // period of time, not just the most recent delta. |
| + RefreshTrafficStats(); |
|
bengr
2015/10/12 21:33:08
Say more. How far behind is TrafficStats?
|
| + |
| + if (!previous_are_traffic_stats_available || !are_traffic_stats_available_) |
| + return; |
| + |
| + int64_t traffic_stats_tx_delta_bytes = |
| + traffic_stats_tx_bytes_ - previous_traffic_stats_tx_bytes; |
| + int64_t traffic_stats_rx_delta_bytes = |
| + traffic_stats_rx_bytes_ - previous_traffic_stats_rx_bytes; |
| + |
| + int64_t total_unamortized_tx_delta_bytes = extra_tx_bytes; |
| + int64_t total_unamortized_rx_delta_bytes = extra_rx_bytes; |
| + for (const DataUse& data_use : *data_use_sequence) { |
| + total_unamortized_tx_delta_bytes += data_use.tx_bytes; |
| + total_unamortized_rx_delta_bytes += data_use.rx_bytes; |
| + } |
| + |
| + const double tx_ratio = static_cast<double>(traffic_stats_tx_delta_bytes) / |
| + static_cast<double>(total_unamortized_tx_delta_bytes); |
|
tbansal1
2015/10/12 21:23:20
can this give divide by 0 error? It probably can d
bengr
2015/10/12 21:33:08
Agreed.
|
| + const double rx_ratio = static_cast<double>(traffic_stats_rx_delta_bytes) / |
| + static_cast<double>(total_unamortized_rx_delta_bytes); |
| + |
| + double tx_remainder = 0.0; |
| + double rx_remainder = 0.0; |
| + for (DataUse& data_use : *data_use_sequence) { |
| + data_use.tx_bytes = |
| + AmortizeByRatio(data_use.tx_bytes, tx_ratio, &tx_remainder); |
| + data_use.rx_bytes = |
| + AmortizeByRatio(data_use.rx_bytes, rx_ratio, &rx_remainder); |
| + } |
|
tbansal1
2015/10/12 21:23:20
DCHECK that tx_remainder and rx_remainder < 1 and
|
| + |
| + // TODO(sclittle): Maybe record some UMA comparing amortized values to |
| + // unamortized values? |
| +} |
| + |
| +bool TrafficStatsAmortizer::GetTrafficStatsTxBytes(int64_t* tx_bytes) const { |
| + return net::android::traffic_stats::GetCurrentUidTxBytes(tx_bytes); |
|
tbansal1
2015/10/12 21:23:20
DCHECK(thread_checker_...)
|
| +} |
| + |
| +bool TrafficStatsAmortizer::GetTrafficStatsRxBytes(int64_t* rx_bytes) const { |
| + return net::android::traffic_stats::GetCurrentUidRxBytes(rx_bytes); |
| +} |
| + |
| +void TrafficStatsAmortizer::RefreshTrafficStats() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + are_traffic_stats_available_ = |
| + GetTrafficStatsTxBytes(&traffic_stats_tx_bytes_) && |
|
bengr
2015/10/12 21:33:08
Can tx_bytes_ or rx_bytes_ be 0?
|
| + GetTrafficStatsRxBytes(&traffic_stats_rx_bytes_); |
| +} |
| + |
| +} // namespace android |
| +} // namespace data_usage |