| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/nqe/network_quality_estimator.h" | 5 #include "net/nqe/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <utility> | 10 #include <utility> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/metrics/histogram_base.h" | 16 #include "base/metrics/histogram_base.h" |
| 17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
| 18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
| 20 #include "base/time/default_tick_clock.h" |
| 20 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 22 #include "net/base/load_flags.h" | 23 #include "net/base/load_flags.h" |
| 23 #include "net/base/load_timing_info.h" | 24 #include "net/base/load_timing_info.h" |
| 24 #include "net/base/network_interfaces.h" | 25 #include "net/base/network_interfaces.h" |
| 25 #include "net/base/url_util.h" | 26 #include "net/base/url_util.h" |
| 26 #include "net/nqe/throughput_analyzer.h" | 27 #include "net/nqe/throughput_analyzer.h" |
| 27 #include "net/socket/socket_performance_watcher.h" | 28 #include "net/socket/socket_performance_watcher.h" |
| 28 #include "net/url_request/url_request.h" | 29 #include "net/url_request/url_request.h" |
| 29 #include "url/gurl.h" | 30 #include "url/gurl.h" |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 246 |
| 246 NetworkQualityEstimator::NetworkQualityEstimator( | 247 NetworkQualityEstimator::NetworkQualityEstimator( |
| 247 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 248 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 248 const std::map<std::string, std::string>& variation_params, | 249 const std::map<std::string, std::string>& variation_params, |
| 249 bool use_local_host_requests_for_tests, | 250 bool use_local_host_requests_for_tests, |
| 250 bool use_smaller_responses_for_tests) | 251 bool use_smaller_responses_for_tests) |
| 251 : use_localhost_requests_(use_local_host_requests_for_tests), | 252 : use_localhost_requests_(use_local_host_requests_for_tests), |
| 252 use_small_responses_(use_smaller_responses_for_tests), | 253 use_small_responses_(use_smaller_responses_for_tests), |
| 253 weight_multiplier_per_second_( | 254 weight_multiplier_per_second_( |
| 254 GetWeightMultiplierPerSecond(variation_params)), | 255 GetWeightMultiplierPerSecond(variation_params)), |
| 255 last_connection_change_(base::TimeTicks::Now()), | 256 tick_clock_(new base::DefaultTickClock()), |
| 257 effective_connection_type_recomputation_interval_( |
| 258 base::TimeDelta::FromSeconds(15)), |
| 259 last_connection_change_(tick_clock_->NowTicks()), |
| 256 current_network_id_( | 260 current_network_id_( |
| 257 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 261 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 258 std::string())), | 262 std::string())), |
| 259 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 263 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
| 260 rtt_observations_(weight_multiplier_per_second_), | 264 rtt_observations_(weight_multiplier_per_second_), |
| 261 external_estimate_provider_(std::move(external_estimates_provider)), | 265 external_estimate_provider_(std::move(external_estimates_provider)), |
| 266 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 262 weak_ptr_factory_(this) { | 267 weak_ptr_factory_(this) { |
| 263 static_assert(kDefaultHalfLifeSeconds > 0, | 268 static_assert(kDefaultHalfLifeSeconds > 0, |
| 264 "Default half life duration must be > 0"); | 269 "Default half life duration must be > 0"); |
| 265 static_assert(kMaximumNetworkQualityCacheSize > 0, | 270 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 266 "Size of the network quality cache must be > 0"); | 271 "Size of the network quality cache must be > 0"); |
| 267 // This limit should not be increased unless the logic for removing the | 272 // This limit should not be increased unless the logic for removing the |
| 268 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 273 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 269 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 274 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 270 "Size of the network quality cache must <= 10"); | 275 "Size of the network quality cache must <= 10"); |
| 271 | 276 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 } | 400 } |
| 396 } | 401 } |
| 397 | 402 |
| 398 void NetworkQualityEstimator::AddDefaultEstimates() { | 403 void NetworkQualityEstimator::AddDefaultEstimates() { |
| 399 DCHECK(thread_checker_.CalledOnValidThread()); | 404 DCHECK(thread_checker_.CalledOnValidThread()); |
| 400 | 405 |
| 401 if (default_observations_[current_network_id_.type].http_rtt() != | 406 if (default_observations_[current_network_id_.type].http_rtt() != |
| 402 nqe::internal::InvalidRTT()) { | 407 nqe::internal::InvalidRTT()) { |
| 403 RttObservation rtt_observation( | 408 RttObservation rtt_observation( |
| 404 default_observations_[current_network_id_.type].http_rtt(), | 409 default_observations_[current_network_id_.type].http_rtt(), |
| 405 base::TimeTicks::Now(), | 410 tick_clock_->NowTicks(), |
| 406 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); | 411 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 407 rtt_observations_.AddObservation(rtt_observation); | 412 rtt_observations_.AddObservation(rtt_observation); |
| 408 NotifyObserversOfRTT(rtt_observation); | 413 NotifyObserversOfRTT(rtt_observation); |
| 409 } | 414 } |
| 410 | 415 |
| 411 if (default_observations_[current_network_id_.type] | 416 if (default_observations_[current_network_id_.type] |
| 412 .downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) { | 417 .downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) { |
| 413 ThroughputObservation throughput_observation( | 418 ThroughputObservation throughput_observation( |
| 414 default_observations_[current_network_id_.type] | 419 default_observations_[current_network_id_.type] |
| 415 .downstream_throughput_kbps(), | 420 .downstream_throughput_kbps(), |
| 416 base::TimeTicks::Now(), | 421 tick_clock_->NowTicks(), |
| 417 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); | 422 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 418 downstream_throughput_kbps_observations_.AddObservation( | 423 downstream_throughput_kbps_observations_.AddObservation( |
| 419 throughput_observation); | 424 throughput_observation); |
| 420 NotifyObserversOfThroughput(throughput_observation); | 425 NotifyObserversOfThroughput(throughput_observation); |
| 421 } | 426 } |
| 422 } | 427 } |
| 423 | 428 |
| 424 NetworkQualityEstimator::~NetworkQualityEstimator() { | 429 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 425 DCHECK(thread_checker_.CalledOnValidThread()); | 430 DCHECK(thread_checker_.CalledOnValidThread()); |
| 426 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 431 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 456 if (!GetDownlinkThroughputKbpsEstimate(&downstream_throughput_kbps)) | 461 if (!GetDownlinkThroughputKbpsEstimate(&downstream_throughput_kbps)) |
| 457 downstream_throughput_kbps = nqe::internal::kInvalidThroughput; | 462 downstream_throughput_kbps = nqe::internal::kInvalidThroughput; |
| 458 | 463 |
| 459 estimated_median_network_quality_ = nqe::internal::NetworkQuality( | 464 estimated_median_network_quality_ = nqe::internal::NetworkQuality( |
| 460 estimated_http_rtt, nqe::internal::InvalidRTT(), | 465 estimated_http_rtt, nqe::internal::InvalidRTT(), |
| 461 downstream_throughput_kbps); | 466 downstream_throughput_kbps); |
| 462 | 467 |
| 463 RecordMetricsOnMainFrameRequest(); | 468 RecordMetricsOnMainFrameRequest(); |
| 464 } | 469 } |
| 465 | 470 |
| 466 base::TimeTicks now = base::TimeTicks::Now(); | 471 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 467 LoadTimingInfo load_timing_info; | 472 LoadTimingInfo load_timing_info; |
| 468 request.GetLoadTimingInfo(&load_timing_info); | 473 request.GetLoadTimingInfo(&load_timing_info); |
| 469 | 474 |
| 470 // If the load timing info is unavailable, it probably means that the request | 475 // If the load timing info is unavailable, it probably means that the request |
| 471 // did not go over the network. | 476 // did not go over the network. |
| 472 if (load_timing_info.send_start.is_null() || | 477 if (load_timing_info.send_start.is_null() || |
| 473 load_timing_info.receive_headers_end.is_null()) { | 478 load_timing_info.receive_headers_end.is_null()) { |
| 474 return; | 479 return; |
| 475 } | 480 } |
| 476 | 481 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 void NetworkQualityEstimator::OnConnectionTypeChanged( | 609 void NetworkQualityEstimator::OnConnectionTypeChanged( |
| 605 NetworkChangeNotifier::ConnectionType type) { | 610 NetworkChangeNotifier::ConnectionType type) { |
| 606 DCHECK(thread_checker_.CalledOnValidThread()); | 611 DCHECK(thread_checker_.CalledOnValidThread()); |
| 607 | 612 |
| 608 RecordMetricsOnConnectionTypeChanged(); | 613 RecordMetricsOnConnectionTypeChanged(); |
| 609 | 614 |
| 610 // Write the estimates of the previous network to the cache. | 615 // Write the estimates of the previous network to the cache. |
| 611 CacheNetworkQualityEstimate(); | 616 CacheNetworkQualityEstimate(); |
| 612 | 617 |
| 613 // Clear the local state. | 618 // Clear the local state. |
| 614 last_connection_change_ = base::TimeTicks::Now(); | 619 last_connection_change_ = tick_clock_->NowTicks(); |
| 615 peak_network_quality_ = nqe::internal::NetworkQuality(); | 620 peak_network_quality_ = nqe::internal::NetworkQuality(); |
| 616 downstream_throughput_kbps_observations_.Clear(); | 621 downstream_throughput_kbps_observations_.Clear(); |
| 617 rtt_observations_.Clear(); | 622 rtt_observations_.Clear(); |
| 618 current_network_id_ = GetCurrentNetworkID(); | 623 current_network_id_ = GetCurrentNetworkID(); |
| 619 | 624 |
| 620 // Query the external estimate provider on certain connection types. Once the | 625 // Query the external estimate provider on certain connection types. Once the |
| 621 // updated estimates are available, OnUpdatedEstimateAvailable will be called | 626 // updated estimates are available, OnUpdatedEstimateAvailable will be called |
| 622 // by |external_estimate_provider_| with updated estimates. | 627 // by |external_estimate_provider_| with updated estimates. |
| 623 if (external_estimate_provider_ && | 628 if (external_estimate_provider_ && |
| 624 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && | 629 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && |
| 625 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && | 630 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && |
| 626 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && | 631 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && |
| 627 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { | 632 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { |
| 628 RecordExternalEstimateProviderMetrics( | 633 RecordExternalEstimateProviderMetrics( |
| 629 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); | 634 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); |
| 630 external_estimate_provider_->Update(); | 635 external_estimate_provider_->Update(); |
| 631 } | 636 } |
| 632 | 637 |
| 633 // Read any cached estimates for the new network. If cached estimates are | 638 // Read any cached estimates for the new network. If cached estimates are |
| 634 // unavailable, add the default estimates. | 639 // unavailable, add the default estimates. |
| 635 if (!ReadCachedNetworkQualityEstimate()) | 640 if (!ReadCachedNetworkQualityEstimate()) |
| 636 AddDefaultEstimates(); | 641 AddDefaultEstimates(); |
| 637 estimated_median_network_quality_ = nqe::internal::NetworkQuality(); | 642 estimated_median_network_quality_ = nqe::internal::NetworkQuality(); |
| 638 throughput_analyzer_->OnConnectionTypeChanged(); | 643 throughput_analyzer_->OnConnectionTypeChanged(); |
| 644 MaybeRecomputeEffectiveConnectionType(); |
| 639 } | 645 } |
| 640 | 646 |
| 641 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { | 647 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { |
| 642 DCHECK(thread_checker_.CalledOnValidThread()); | 648 DCHECK(thread_checker_.CalledOnValidThread()); |
| 643 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { | 649 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { |
| 644 base::HistogramBase* rtt_histogram = | 650 base::HistogramBase* rtt_histogram = |
| 645 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); | 651 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); |
| 646 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); | 652 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); |
| 647 } | 653 } |
| 648 | 654 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 if (estimated_http_rtt_is_higher_than_threshold || | 797 if (estimated_http_rtt_is_higher_than_threshold || |
| 792 estimated_throughput_is_lower_than_threshold) { | 798 estimated_throughput_is_lower_than_threshold) { |
| 793 return type; | 799 return type; |
| 794 } | 800 } |
| 795 } | 801 } |
| 796 // Return the fastest connection type. | 802 // Return the fastest connection type. |
| 797 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | 803 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - |
| 798 1); | 804 1); |
| 799 } | 805 } |
| 800 | 806 |
| 807 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( |
| 808 EffectiveConnectionTypeObserver* observer) { |
| 809 DCHECK(thread_checker_.CalledOnValidThread()); |
| 810 effective_connection_type_observer_list_.AddObserver(observer); |
| 811 } |
| 812 |
| 813 void NetworkQualityEstimator::RemoveEffectiveConnectionTypeObserver( |
| 814 EffectiveConnectionTypeObserver* observer) { |
| 815 DCHECK(thread_checker_.CalledOnValidThread()); |
| 816 effective_connection_type_observer_list_.RemoveObserver(observer); |
| 817 } |
| 818 |
| 801 bool NetworkQualityEstimator::GetHttpRTTEstimate(base::TimeDelta* rtt) const { | 819 bool NetworkQualityEstimator::GetHttpRTTEstimate(base::TimeDelta* rtt) const { |
| 802 DCHECK(thread_checker_.CalledOnValidThread()); | 820 DCHECK(thread_checker_.CalledOnValidThread()); |
| 803 return GetRecentHttpRTTMedian(base::TimeTicks(), rtt); | 821 return GetRecentHttpRTTMedian(base::TimeTicks(), rtt); |
| 804 } | 822 } |
| 805 | 823 |
| 806 bool NetworkQualityEstimator::GetTransportRTTEstimate( | 824 bool NetworkQualityEstimator::GetTransportRTTEstimate( |
| 807 base::TimeDelta* rtt) const { | 825 base::TimeDelta* rtt) const { |
| 808 DCHECK(thread_checker_.CalledOnValidThread()); | 826 DCHECK(thread_checker_.CalledOnValidThread()); |
| 809 return GetRecentTransportRTTMedian(base::TimeTicks(), rtt); | 827 return GetRecentTransportRTTMedian(base::TimeTicks(), rtt); |
| 810 } | 828 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 return false; | 961 return false; |
| 944 | 962 |
| 945 CachedNetworkQualities::const_iterator it = | 963 CachedNetworkQualities::const_iterator it = |
| 946 cached_network_qualities_.find(current_network_id_); | 964 cached_network_qualities_.find(current_network_id_); |
| 947 | 965 |
| 948 if (it == cached_network_qualities_.end()) | 966 if (it == cached_network_qualities_.end()) |
| 949 return false; | 967 return false; |
| 950 | 968 |
| 951 nqe::internal::NetworkQuality network_quality(it->second.network_quality()); | 969 nqe::internal::NetworkQuality network_quality(it->second.network_quality()); |
| 952 | 970 |
| 953 const base::TimeTicks now = base::TimeTicks::Now(); | 971 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 954 bool read_cached_estimate = false; | 972 bool read_cached_estimate = false; |
| 955 | 973 |
| 956 if (network_quality.downstream_throughput_kbps() != | 974 if (network_quality.downstream_throughput_kbps() != |
| 957 nqe::internal::kInvalidThroughput) { | 975 nqe::internal::kInvalidThroughput) { |
| 958 read_cached_estimate = true; | 976 read_cached_estimate = true; |
| 959 ThroughputObservation througphput_observation( | 977 ThroughputObservation througphput_observation( |
| 960 network_quality.downstream_throughput_kbps(), now, | 978 network_quality.downstream_throughput_kbps(), now, |
| 961 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); | 979 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); |
| 962 downstream_throughput_kbps_observations_.AddObservation( | 980 downstream_throughput_kbps_observations_.AddObservation( |
| 963 througphput_observation); | 981 througphput_observation); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 return "4G"; | 1042 return "4G"; |
| 1025 case EFFECTIVE_CONNECTION_TYPE_BROADBAND: | 1043 case EFFECTIVE_CONNECTION_TYPE_BROADBAND: |
| 1026 return "Broadband"; | 1044 return "Broadband"; |
| 1027 default: | 1045 default: |
| 1028 NOTREACHED(); | 1046 NOTREACHED(); |
| 1029 break; | 1047 break; |
| 1030 } | 1048 } |
| 1031 return ""; | 1049 return ""; |
| 1032 } | 1050 } |
| 1033 | 1051 |
| 1052 void NetworkQualityEstimator::SetTickClockForTesting( |
| 1053 std::unique_ptr<base::TickClock> tick_clock) { |
| 1054 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1055 tick_clock_ = std::move(tick_clock); |
| 1056 } |
| 1057 |
| 1034 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | 1058 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
| 1035 DCHECK(thread_checker_.CalledOnValidThread()); | 1059 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1036 DCHECK_LE(cached_network_qualities_.size(), | 1060 DCHECK_LE(cached_network_qualities_.size(), |
| 1037 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 1061 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 1038 | 1062 |
| 1039 // If the network name is unavailable, caching should not be performed. | 1063 // If the network name is unavailable, caching should not be performed. |
| 1040 if (current_network_id_.id.empty()) | 1064 if (current_network_id_.id.empty()) |
| 1041 return; | 1065 return; |
| 1042 | 1066 |
| 1043 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); | 1067 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 DCHECK_LE(cached_network_qualities_.size(), | 1099 DCHECK_LE(cached_network_qualities_.size(), |
| 1076 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 1100 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 1077 } | 1101 } |
| 1078 | 1102 |
| 1079 void NetworkQualityEstimator::OnUpdatedRTTAvailable( | 1103 void NetworkQualityEstimator::OnUpdatedRTTAvailable( |
| 1080 SocketPerformanceWatcherFactory::Protocol protocol, | 1104 SocketPerformanceWatcherFactory::Protocol protocol, |
| 1081 const base::TimeDelta& rtt) { | 1105 const base::TimeDelta& rtt) { |
| 1082 DCHECK(thread_checker_.CalledOnValidThread()); | 1106 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1083 DCHECK_NE(nqe::internal::InvalidRTT(), rtt); | 1107 DCHECK_NE(nqe::internal::InvalidRTT(), rtt); |
| 1084 | 1108 |
| 1085 RttObservation observation(rtt, base::TimeTicks::Now(), | 1109 RttObservation observation(rtt, tick_clock_->NowTicks(), |
| 1086 ProtocolSourceToObservationSource(protocol)); | 1110 ProtocolSourceToObservationSource(protocol)); |
| 1087 NotifyObserversOfRTT(observation); | 1111 NotifyObserversOfRTT(observation); |
| 1088 rtt_observations_.AddObservation(observation); | 1112 rtt_observations_.AddObservation(observation); |
| 1089 } | 1113 } |
| 1090 | 1114 |
| 1091 void NetworkQualityEstimator::NotifyObserversOfRTT( | 1115 void NetworkQualityEstimator::NotifyObserversOfRTT( |
| 1092 const RttObservation& observation) { | 1116 const RttObservation& observation) { |
| 1093 DCHECK(thread_checker_.CalledOnValidThread()); | 1117 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1094 DCHECK_NE(nqe::internal::InvalidRTT(), observation.value); | 1118 DCHECK_NE(nqe::internal::InvalidRTT(), observation.value); |
| 1095 | 1119 |
| 1120 // Maybe recompute the effective connection type since a new RTT observation |
| 1121 // is available. |
| 1122 MaybeRecomputeEffectiveConnectionType(); |
| 1096 FOR_EACH_OBSERVER( | 1123 FOR_EACH_OBSERVER( |
| 1097 RTTObserver, rtt_observer_list_, | 1124 RTTObserver, rtt_observer_list_, |
| 1098 OnRTTObservation(observation.value.InMilliseconds(), | 1125 OnRTTObservation(observation.value.InMilliseconds(), |
| 1099 observation.timestamp, observation.source)); | 1126 observation.timestamp, observation.source)); |
| 1100 } | 1127 } |
| 1101 | 1128 |
| 1102 void NetworkQualityEstimator::NotifyObserversOfThroughput( | 1129 void NetworkQualityEstimator::NotifyObserversOfThroughput( |
| 1103 const ThroughputObservation& observation) { | 1130 const ThroughputObservation& observation) { |
| 1104 DCHECK(thread_checker_.CalledOnValidThread()); | 1131 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1105 DCHECK_NE(nqe::internal::kInvalidThroughput, observation.value); | 1132 DCHECK_NE(nqe::internal::kInvalidThroughput, observation.value); |
| 1106 | 1133 |
| 1134 // Maybe recompute the effective connection type since a new throughput |
| 1135 // observation is available. |
| 1136 MaybeRecomputeEffectiveConnectionType(); |
| 1107 FOR_EACH_OBSERVER( | 1137 FOR_EACH_OBSERVER( |
| 1108 ThroughputObserver, throughput_observer_list_, | 1138 ThroughputObserver, throughput_observer_list_, |
| 1109 OnThroughputObservation(observation.value, observation.timestamp, | 1139 OnThroughputObservation(observation.value, observation.timestamp, |
| 1110 observation.source)); | 1140 observation.source)); |
| 1111 } | 1141 } |
| 1112 | 1142 |
| 1113 void NetworkQualityEstimator::OnNewThroughputObservationAvailable( | 1143 void NetworkQualityEstimator::OnNewThroughputObservationAvailable( |
| 1114 int32_t downstream_kbps) { | 1144 int32_t downstream_kbps) { |
| 1115 DCHECK(thread_checker_.CalledOnValidThread()); | 1145 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1116 | 1146 |
| 1117 if (downstream_kbps == 0) | 1147 if (downstream_kbps == 0) |
| 1118 return; | 1148 return; |
| 1119 | 1149 |
| 1120 DCHECK_NE(nqe::internal::kInvalidThroughput, downstream_kbps); | 1150 DCHECK_NE(nqe::internal::kInvalidThroughput, downstream_kbps); |
| 1121 | 1151 |
| 1122 if (downstream_kbps > peak_network_quality_.downstream_throughput_kbps()) { | 1152 if (downstream_kbps > peak_network_quality_.downstream_throughput_kbps()) { |
| 1123 peak_network_quality_ = nqe::internal::NetworkQuality( | 1153 peak_network_quality_ = nqe::internal::NetworkQuality( |
| 1124 peak_network_quality_.http_rtt(), peak_network_quality_.transport_rtt(), | 1154 peak_network_quality_.http_rtt(), peak_network_quality_.transport_rtt(), |
| 1125 downstream_kbps); | 1155 downstream_kbps); |
| 1126 } | 1156 } |
| 1127 ThroughputObservation throughput_observation( | 1157 ThroughputObservation throughput_observation( |
| 1128 downstream_kbps, base::TimeTicks::Now(), | 1158 downstream_kbps, tick_clock_->NowTicks(), |
| 1129 NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); | 1159 NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); |
| 1130 downstream_throughput_kbps_observations_.AddObservation( | 1160 downstream_throughput_kbps_observations_.AddObservation( |
| 1131 throughput_observation); | 1161 throughput_observation); |
| 1132 NotifyObserversOfThroughput(throughput_observation); | 1162 NotifyObserversOfThroughput(throughput_observation); |
| 1133 } | 1163 } |
| 1134 | 1164 |
| 1165 void NetworkQualityEstimator::MaybeRecomputeEffectiveConnectionType() { |
| 1166 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1167 |
| 1168 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 1169 // Recompute effective connection type only if |
| 1170 // |effective_connection_type_recomputation_interval_| has passed since it was |
| 1171 // last computed or a connection change event was observed since the last |
| 1172 // computation. Strict inequalities are used to ensure that effective |
| 1173 // connection type is recomputed on connection change events even if the clock |
| 1174 // has not updated. |
| 1175 if (now - last_effective_connection_type_computation_ < |
| 1176 effective_connection_type_recomputation_interval_ && |
| 1177 last_connection_change_ < last_effective_connection_type_computation_) { |
| 1178 return; |
| 1179 } |
| 1180 |
| 1181 const EffectiveConnectionType past_type = effective_connection_type_; |
| 1182 last_effective_connection_type_computation_ = now; |
| 1183 effective_connection_type_ = GetEffectiveConnectionType(); |
| 1184 |
| 1185 if (past_type != effective_connection_type_) |
| 1186 NotifyObserversOfEffectiveConnectionTypeChanged(); |
| 1187 } |
| 1188 |
| 1189 void NetworkQualityEstimator:: |
| 1190 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1191 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1192 |
| 1193 // TODO(tbansal): Add hysteresis in the notification. |
| 1194 FOR_EACH_OBSERVER( |
| 1195 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1196 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1197 } |
| 1198 |
| 1135 } // namespace net | 1199 } // namespace net |
| OLD | NEW |