Chromium Code Reviews| Index: net/base/network_quality_estimator.cc |
| diff --git a/net/base/network_quality_estimator.cc b/net/base/network_quality_estimator.cc |
| index e012a99d72fdcc752cf4e9406f8e61651315598a..eaa55299623f1348593c352d204e0ae2142d9bc6 100644 |
| --- a/net/base/network_quality_estimator.cc |
| +++ b/net/base/network_quality_estimator.cc |
| @@ -12,8 +12,45 @@ |
| #include "net/url_request/url_request.h" |
| #include "url/gurl.h" |
| +#if defined(OS_ANDROID) |
| +#include "net/android/network_library.h" |
| +#endif // OS_ANDROID |
| + |
| +namespace { |
| + |
| +// Maximum size of the cache that holds network quality estimates. |
| +// Smaller size may reduce the cache hit rate due to frequent evictions. |
| +// Larger size may affect performance. |
| +const uint32_t kMaximumNetworkQualityCacheSize = 5; |
| + |
| +} // namespace |
| + |
| namespace net { |
| +CachedNetworkQuality::CachedNetworkQuality( |
| + NetworkChangeNotifier::ConnectionType connection_type, |
| + std::string network_name, |
| + int median_kbps, |
| + int median_rtt_milliseconds) |
| + : connection_type(connection_type), |
| + network_name(network_name), |
| + median_kbps(median_kbps), |
| + median_rtt_milliseconds(median_rtt_milliseconds), |
| + last_updated(base::TimeTicks::Now()) { |
| + DCHECK_NE(network_name, std::string()); |
| +} |
| + |
| +CachedNetworkQuality::~CachedNetworkQuality() { |
| +} |
| + |
| +void CachedNetworkQuality::UpdateNetworkQuality( |
| + int updated_median_kbps, |
| + int updated_median_rtt_milliseconds) { |
| + median_kbps = updated_median_kbps; |
| + median_rtt_milliseconds = updated_median_rtt_milliseconds; |
| + last_updated = base::TimeTicks::Now(); |
| +} |
| + |
| NetworkQualityEstimator::NetworkQualityEstimator() |
| : NetworkQualityEstimator(false) { |
| } |
| @@ -27,7 +64,10 @@ NetworkQualityEstimator::NetworkQualityEstimator( |
| peak_kbps_since_last_connection_change_(0) { |
| static_assert(kMinRequestDurationMicroseconds > 0, |
| "Minimum request duration must be > 0"); |
| + static_assert(kMaximumNetworkQualityCacheSize > 0, |
| + "Size of the network quality cache must be > 0"); |
| NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| + current_network_name_ = GetCurrentNetworkName(); |
| } |
| NetworkQualityEstimator::~NetworkQualityEstimator() { |
| @@ -109,7 +149,8 @@ void NetworkQualityEstimator::OnConnectionTypeChanged( |
| fastest_RTT_since_last_connection_change_); |
| break; |
| default: |
| - NOTREACHED(); |
| + NOTREACHED() << "Unexpected connection type = " |
| + << current_connection_type_; |
| break; |
| } |
| } |
| @@ -149,15 +190,23 @@ void NetworkQualityEstimator::OnConnectionTypeChanged( |
| peak_kbps_since_last_connection_change_); |
| break; |
| default: |
| - NOTREACHED(); |
| + NOTREACHED() << "Unexpected connection type = " |
| + << current_connection_type_; |
| break; |
| } |
| } |
| + // Write the estimates of the previous network to the cache. |
| + CacheNetworkQualityEstimate(); |
| + |
| last_connection_change_ = base::TimeTicks::Now(); |
| bytes_read_since_last_connection_change_ = false; |
| peak_kbps_since_last_connection_change_ = 0; |
| current_connection_type_ = type; |
| + current_network_name_ = GetCurrentNetworkName(); |
| + |
| + // Read any cached estimates for the new network. |
| + ReadCachedNetworkQualityEstimate(); |
| } |
| NetworkQuality NetworkQualityEstimator::GetEstimate() const { |
| @@ -175,4 +224,104 @@ NetworkQuality NetworkQualityEstimator::GetEstimate() const { |
| peak_kbps_since_last_connection_change_, 0.1); |
| } |
| +std::string NetworkQualityEstimator::GetCurrentNetworkName() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN || |
| + current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_NONE || |
| + current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH) |
| + return std::string(); |
| + |
| + if (current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET) { |
| + return "ethernet"; |
| + } |
| + |
| +#if defined(OS_ANDROID) |
| + if (current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) |
| + return GetWifiSSID(); |
| + if (current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_2G || |
| + current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_3G || |
| + current_connection_type_ == |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_4G) |
| + return android::GetTelephonyNetworkOperator(); |
| + NOTREACHED() << "Unexpected connection type = " << current_connection_type_; |
| +#endif // OS_ANDROID |
| + |
| + return std::string(); |
| +} |
| + |
| +bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (current_network_name_ == "") |
| + return false; |
| + |
| + for (const auto& network_quality : cached_network_quality_) { |
| + if (network_quality.connection_type != current_connection_type_ || |
| + network_quality.network_name != current_network_name_) |
| + continue; |
| + |
| + // TOOD(tbansal): Populate these values back into the median computing |
| + // algorithm. |
| + // Add UMA to record how frequently match happens. |
| + // int64 median_kbps = network_quality.median_kbps; |
| + // int64 median_rtt_msec = network_quality.median_rtt_milliseconds; |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| +void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (current_network_name_ == "") |
| + return; |
| + |
| + // TODO(tbansal): Following variables should be initialized using the median |
| + /// values reported by NetworkQualityEstimator. |
| + int median_kbps = 0; |
| + int median_rtt_milliseconds = 0; |
| + |
| + // If this network is already in the cache, overwrite that entry. |
| + for (auto& network_quality : cached_network_quality_) { |
| + if (network_quality.connection_type != current_connection_type_ || |
| + network_quality.network_name != current_network_name_) |
| + continue; |
| + |
| + network_quality.UpdateNetworkQuality(median_kbps, median_rtt_milliseconds); |
| + return; |
| + } |
| + |
| + if (cached_network_quality_.size() < kMaximumNetworkQualityCacheSize) { |
| + cached_network_quality_.push_back( |
| + CachedNetworkQuality(current_connection_type_, current_network_name_, |
| + median_kbps, median_rtt_milliseconds)); |
| + return; |
| + } |
| + |
| + DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size()); |
| + |
| + // Overwrite the oldest entry. |
| + int oldest_entry_index = 0; |
| + for (size_t i = 0; i < cached_network_quality_.size(); ++i) { |
| + if (cached_network_quality_[i].last_updated < |
| + cached_network_quality_[oldest_entry_index].last_updated) |
| + oldest_entry_index = i; |
| + } |
| + |
| + cached_network_quality_[oldest_entry_index] = |
| + CachedNetworkQuality(current_connection_type_, current_network_name_, |
| + median_kbps, median_rtt_milliseconds); |
| + |
| + DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size()); |
|
mmenke
2015/05/28 15:25:02
include base/logging.h for DCHECK and NOTREACHED.
tbansal1
2015/05/29 02:27:23
Done.
|
| +} |
| + |
| } // namespace net |