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 |