| 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> |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "net/base/load_flags.h" | 24 #include "net/base/load_flags.h" |
| 25 #include "net/base/load_timing_info.h" | 25 #include "net/base/load_timing_info.h" |
| 26 #include "net/base/network_interfaces.h" | 26 #include "net/base/network_interfaces.h" |
| 27 #include "net/base/url_util.h" | 27 #include "net/base/url_util.h" |
| 28 #include "net/nqe/socket_watcher_factory.h" | 28 #include "net/nqe/socket_watcher_factory.h" |
| 29 #include "net/nqe/throughput_analyzer.h" | 29 #include "net/nqe/throughput_analyzer.h" |
| 30 #include "net/url_request/url_request.h" | 30 #include "net/url_request/url_request.h" |
| 31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
| 32 | 32 |
| 33 #if defined(OS_ANDROID) | 33 #if defined(OS_ANDROID) |
| 34 #include "net/android/cellular_signal_strength.h" |
| 34 #include "net/android/network_library.h" | 35 #include "net/android/network_library.h" |
| 35 #endif // OS_ANDROID | 36 #endif // OS_ANDROID |
| 36 | 37 |
| 37 namespace { | 38 namespace { |
| 38 | 39 |
| 39 // Default value of the half life (in seconds) for computing time weighted | 40 // Default value of the half life (in seconds) for computing time weighted |
| 40 // percentiles. Every half life, the weight of all observations reduces by | 41 // percentiles. Every half life, the weight of all observations reduces by |
| 41 // half. Lowering the half life would reduce the weight of older values faster. | 42 // half. Lowering the half life would reduce the weight of older values faster. |
| 42 const int kDefaultHalfLifeSeconds = 60; | 43 const int kDefaultHalfLifeSeconds = 60; |
| 43 | 44 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 effective_connection_type_recomputation_interval_( | 224 effective_connection_type_recomputation_interval_( |
| 224 base::TimeDelta::FromSeconds(15)), | 225 base::TimeDelta::FromSeconds(15)), |
| 225 last_connection_change_(tick_clock_->NowTicks()), | 226 last_connection_change_(tick_clock_->NowTicks()), |
| 226 current_network_id_( | 227 current_network_id_( |
| 227 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 228 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 228 std::string())), | 229 std::string())), |
| 229 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 230 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
| 230 rtt_observations_(weight_multiplier_per_second_), | 231 rtt_observations_(weight_multiplier_per_second_), |
| 231 external_estimate_provider_(std::move(external_estimates_provider)), | 232 external_estimate_provider_(std::move(external_estimates_provider)), |
| 232 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 233 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 234 min_signal_strength_since_connection_change_(INT32_MAX), |
| 235 max_signal_strength_since_connection_change_(INT32_MIN), |
| 233 weak_ptr_factory_(this) { | 236 weak_ptr_factory_(this) { |
| 234 static_assert(kDefaultHalfLifeSeconds > 0, | 237 static_assert(kDefaultHalfLifeSeconds > 0, |
| 235 "Default half life duration must be > 0"); | 238 "Default half life duration must be > 0"); |
| 236 static_assert(kMaximumNetworkQualityCacheSize > 0, | 239 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 237 "Size of the network quality cache must be > 0"); | 240 "Size of the network quality cache must be > 0"); |
| 238 // This limit should not be increased unless the logic for removing the | 241 // This limit should not be increased unless the logic for removing the |
| 239 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 242 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 240 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 243 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 241 "Size of the network quality cache must <= 10"); | 244 "Size of the network quality cache must <= 10"); |
| 242 // None of the algorithms can have an empty name. | 245 // None of the algorithms can have an empty name. |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 // possible to measure the accuracy by comparing the estimate with the | 475 // possible to measure the accuracy by comparing the estimate with the |
| 473 // observations received over intervals of varying durations. | 476 // observations received over intervals of varying durations. |
| 474 for (const base::TimeDelta& measuring_delay : | 477 for (const base::TimeDelta& measuring_delay : |
| 475 GetAccuracyRecordingIntervals()) { | 478 GetAccuracyRecordingIntervals()) { |
| 476 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 479 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 477 FROM_HERE, | 480 FROM_HERE, |
| 478 base::Bind(&NetworkQualityEstimator::RecordAccuracyAfterMainFrame, | 481 base::Bind(&NetworkQualityEstimator::RecordAccuracyAfterMainFrame, |
| 479 weak_ptr_factory_.GetWeakPtr(), measuring_delay), | 482 weak_ptr_factory_.GetWeakPtr(), measuring_delay), |
| 480 measuring_delay); | 483 measuring_delay); |
| 481 } | 484 } |
| 485 UpdateSignalStrength(); |
| 482 } | 486 } |
| 483 | 487 |
| 484 LoadTimingInfo load_timing_info; | 488 LoadTimingInfo load_timing_info; |
| 485 request.GetLoadTimingInfo(&load_timing_info); | 489 request.GetLoadTimingInfo(&load_timing_info); |
| 486 | 490 |
| 487 // If the load timing info is unavailable, it probably means that the request | 491 // If the load timing info is unavailable, it probably means that the request |
| 488 // did not go over the network. | 492 // did not go over the network. |
| 489 if (load_timing_info.send_start.is_null() || | 493 if (load_timing_info.send_start.is_null() || |
| 490 load_timing_info.receive_headers_end.is_null()) { | 494 load_timing_info.receive_headers_end.is_null()) { |
| 491 return; | 495 return; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 RecordMetricsOnConnectionTypeChanged(); | 651 RecordMetricsOnConnectionTypeChanged(); |
| 648 | 652 |
| 649 // Write the estimates of the previous network to the cache. | 653 // Write the estimates of the previous network to the cache. |
| 650 CacheNetworkQualityEstimate(); | 654 CacheNetworkQualityEstimate(); |
| 651 | 655 |
| 652 // Clear the local state. | 656 // Clear the local state. |
| 653 last_connection_change_ = tick_clock_->NowTicks(); | 657 last_connection_change_ = tick_clock_->NowTicks(); |
| 654 peak_network_quality_ = nqe::internal::NetworkQuality(); | 658 peak_network_quality_ = nqe::internal::NetworkQuality(); |
| 655 downstream_throughput_kbps_observations_.Clear(); | 659 downstream_throughput_kbps_observations_.Clear(); |
| 656 rtt_observations_.Clear(); | 660 rtt_observations_.Clear(); |
| 661 |
| 662 #if defined(OS_ANDROID) |
| 663 if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) { |
| 664 UMA_HISTOGRAM_BOOLEAN( |
| 665 "NQE.CellularRSSIAvailable", |
| 666 min_signal_strength_since_connection_change_ != INT32_MAX && |
| 667 max_signal_strength_since_connection_change_ != INT32_MIN); |
| 668 } |
| 669 #endif // OS_ANDROID |
| 670 min_signal_strength_since_connection_change_ = INT32_MAX; |
| 671 max_signal_strength_since_connection_change_ = INT32_MIN; |
| 672 |
| 657 current_network_id_ = GetCurrentNetworkID(); | 673 current_network_id_ = GetCurrentNetworkID(); |
| 658 | 674 |
| 659 // Query the external estimate provider on certain connection types. Once the | 675 // Query the external estimate provider on certain connection types. Once the |
| 660 // updated estimates are available, OnUpdatedEstimateAvailable will be called | 676 // updated estimates are available, OnUpdatedEstimateAvailable will be called |
| 661 // by |external_estimate_provider_| with updated estimates. | 677 // by |external_estimate_provider_| with updated estimates. |
| 662 if (external_estimate_provider_ && | 678 if (external_estimate_provider_ && |
| 663 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && | 679 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && |
| 664 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && | 680 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && |
| 665 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && | 681 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && |
| 666 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { | 682 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { |
| 667 RecordExternalEstimateProviderMetrics( | 683 RecordExternalEstimateProviderMetrics( |
| 668 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); | 684 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); |
| 669 external_estimate_provider_->Update(); | 685 external_estimate_provider_->Update(); |
| 670 } | 686 } |
| 671 | 687 |
| 672 // Read any cached estimates for the new network. If cached estimates are | 688 // Read any cached estimates for the new network. If cached estimates are |
| 673 // unavailable, add the default estimates. | 689 // unavailable, add the default estimates. |
| 674 if (!ReadCachedNetworkQualityEstimate()) | 690 if (!ReadCachedNetworkQualityEstimate()) |
| 675 AddDefaultEstimates(); | 691 AddDefaultEstimates(); |
| 676 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); | 692 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); |
| 677 throughput_analyzer_->OnConnectionTypeChanged(); | 693 throughput_analyzer_->OnConnectionTypeChanged(); |
| 678 MaybeRecomputeEffectiveConnectionType(); | 694 MaybeRecomputeEffectiveConnectionType(); |
| 695 UpdateSignalStrength(); |
| 696 } |
| 697 |
| 698 void NetworkQualityEstimator::UpdateSignalStrength() { |
| 699 #if defined(OS_ANDROID) |
| 700 int32_t signal_strength_dbm; |
| 701 if (!android::cellular_signal_strength::GetSignalStrengthDbm( |
| 702 &signal_strength_dbm)) { |
| 703 return; |
| 704 } |
| 705 min_signal_strength_since_connection_change_ = std::min( |
| 706 min_signal_strength_since_connection_change_, signal_strength_dbm); |
| 707 max_signal_strength_since_connection_change_ = std::max( |
| 708 max_signal_strength_since_connection_change_, signal_strength_dbm); |
| 709 #endif // OS_ANDROID |
| 679 } | 710 } |
| 680 | 711 |
| 681 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { | 712 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { |
| 682 DCHECK(thread_checker_.CalledOnValidThread()); | 713 DCHECK(thread_checker_.CalledOnValidThread()); |
| 683 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { | 714 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { |
| 684 base::HistogramBase* rtt_histogram = | 715 base::HistogramBase* rtt_histogram = |
| 685 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); | 716 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); |
| 686 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); | 717 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); |
| 687 } | 718 } |
| 688 | 719 |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1293 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1263 DCHECK(thread_checker_.CalledOnValidThread()); | 1294 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1264 | 1295 |
| 1265 // TODO(tbansal): Add hysteresis in the notification. | 1296 // TODO(tbansal): Add hysteresis in the notification. |
| 1266 FOR_EACH_OBSERVER( | 1297 FOR_EACH_OBSERVER( |
| 1267 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1298 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1268 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1299 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1269 } | 1300 } |
| 1270 | 1301 |
| 1271 } // namespace net | 1302 } // namespace net |
| OLD | NEW |