| 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 last_connection_change_(tick_clock_->NowTicks()), | 246 last_connection_change_(tick_clock_->NowTicks()), |
| 246 current_network_id_( | 247 current_network_id_( |
| 247 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 248 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 248 std::string())), | 249 std::string())), |
| 249 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 250 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
| 250 rtt_observations_(weight_multiplier_per_second_), | 251 rtt_observations_(weight_multiplier_per_second_), |
| 251 effective_connection_type_at_last_main_frame_( | 252 effective_connection_type_at_last_main_frame_( |
| 252 EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 253 EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 253 external_estimate_provider_(std::move(external_estimates_provider)), | 254 external_estimate_provider_(std::move(external_estimates_provider)), |
| 254 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 255 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 256 min_signal_strength_since_connection_change_(INT32_MAX), |
| 257 max_signal_strength_since_connection_change_(INT32_MIN), |
| 255 weak_ptr_factory_(this) { | 258 weak_ptr_factory_(this) { |
| 256 static_assert(kDefaultHalfLifeSeconds > 0, | 259 static_assert(kDefaultHalfLifeSeconds > 0, |
| 257 "Default half life duration must be > 0"); | 260 "Default half life duration must be > 0"); |
| 258 static_assert(kMaximumNetworkQualityCacheSize > 0, | 261 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 259 "Size of the network quality cache must be > 0"); | 262 "Size of the network quality cache must be > 0"); |
| 260 // This limit should not be increased unless the logic for removing the | 263 // This limit should not be increased unless the logic for removing the |
| 261 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 264 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 262 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 265 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 263 "Size of the network quality cache must <= 10"); | 266 "Size of the network quality cache must <= 10"); |
| 264 // None of the algorithms can have an empty name. | 267 // None of the algorithms can have an empty name. |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 // possible to measure the accuracy by comparing the estimate with the | 499 // possible to measure the accuracy by comparing the estimate with the |
| 497 // observations received over intervals of varying durations. | 500 // observations received over intervals of varying durations. |
| 498 for (const base::TimeDelta& measuring_delay : | 501 for (const base::TimeDelta& measuring_delay : |
| 499 GetAccuracyRecordingIntervals()) { | 502 GetAccuracyRecordingIntervals()) { |
| 500 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 503 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 501 FROM_HERE, | 504 FROM_HERE, |
| 502 base::Bind(&NetworkQualityEstimator::RecordAccuracyAfterMainFrame, | 505 base::Bind(&NetworkQualityEstimator::RecordAccuracyAfterMainFrame, |
| 503 weak_ptr_factory_.GetWeakPtr(), measuring_delay), | 506 weak_ptr_factory_.GetWeakPtr(), measuring_delay), |
| 504 measuring_delay); | 507 measuring_delay); |
| 505 } | 508 } |
| 509 UpdateSignalStrength(); |
| 506 } | 510 } |
| 507 | 511 |
| 508 LoadTimingInfo load_timing_info; | 512 LoadTimingInfo load_timing_info; |
| 509 request.GetLoadTimingInfo(&load_timing_info); | 513 request.GetLoadTimingInfo(&load_timing_info); |
| 510 | 514 |
| 511 // If the load timing info is unavailable, it probably means that the request | 515 // If the load timing info is unavailable, it probably means that the request |
| 512 // did not go over the network. | 516 // did not go over the network. |
| 513 if (load_timing_info.send_start.is_null() || | 517 if (load_timing_info.send_start.is_null() || |
| 514 load_timing_info.receive_headers_end.is_null()) { | 518 load_timing_info.receive_headers_end.is_null()) { |
| 515 return; | 519 return; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 RecordMetricsOnConnectionTypeChanged(); | 737 RecordMetricsOnConnectionTypeChanged(); |
| 734 | 738 |
| 735 // Write the estimates of the previous network to the cache. | 739 // Write the estimates of the previous network to the cache. |
| 736 CacheNetworkQualityEstimate(); | 740 CacheNetworkQualityEstimate(); |
| 737 | 741 |
| 738 // Clear the local state. | 742 // Clear the local state. |
| 739 last_connection_change_ = tick_clock_->NowTicks(); | 743 last_connection_change_ = tick_clock_->NowTicks(); |
| 740 peak_network_quality_ = nqe::internal::NetworkQuality(); | 744 peak_network_quality_ = nqe::internal::NetworkQuality(); |
| 741 downstream_throughput_kbps_observations_.Clear(); | 745 downstream_throughput_kbps_observations_.Clear(); |
| 742 rtt_observations_.Clear(); | 746 rtt_observations_.Clear(); |
| 747 |
| 748 #if defined(OS_ANDROID) |
| 749 if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) { |
| 750 UMA_HISTOGRAM_BOOLEAN( |
| 751 "NQE.CellularSignalStrengthAvailable", |
| 752 min_signal_strength_since_connection_change_ != INT32_MAX && |
| 753 max_signal_strength_since_connection_change_ != INT32_MIN); |
| 754 } |
| 755 #endif // OS_ANDROID |
| 756 min_signal_strength_since_connection_change_ = INT32_MAX; |
| 757 max_signal_strength_since_connection_change_ = INT32_MIN; |
| 758 |
| 743 current_network_id_ = GetCurrentNetworkID(); | 759 current_network_id_ = GetCurrentNetworkID(); |
| 744 | 760 |
| 745 // Query the external estimate provider on certain connection types. Once the | 761 // Query the external estimate provider on certain connection types. Once the |
| 746 // updated estimates are available, OnUpdatedEstimateAvailable will be called | 762 // updated estimates are available, OnUpdatedEstimateAvailable will be called |
| 747 // by |external_estimate_provider_| with updated estimates. | 763 // by |external_estimate_provider_| with updated estimates. |
| 748 if (external_estimate_provider_ && | 764 if (external_estimate_provider_ && |
| 749 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && | 765 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && |
| 750 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && | 766 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && |
| 751 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && | 767 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && |
| 752 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { | 768 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { |
| 753 RecordExternalEstimateProviderMetrics( | 769 RecordExternalEstimateProviderMetrics( |
| 754 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); | 770 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); |
| 755 external_estimate_provider_->Update(); | 771 external_estimate_provider_->Update(); |
| 756 } | 772 } |
| 757 | 773 |
| 758 // Read any cached estimates for the new network. If cached estimates are | 774 // Read any cached estimates for the new network. If cached estimates are |
| 759 // unavailable, add the default estimates. | 775 // unavailable, add the default estimates. |
| 760 if (!ReadCachedNetworkQualityEstimate()) | 776 if (!ReadCachedNetworkQualityEstimate()) |
| 761 AddDefaultEstimates(); | 777 AddDefaultEstimates(); |
| 762 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); | 778 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); |
| 763 throughput_analyzer_->OnConnectionTypeChanged(); | 779 throughput_analyzer_->OnConnectionTypeChanged(); |
| 764 MaybeRecomputeEffectiveConnectionType(); | 780 MaybeRecomputeEffectiveConnectionType(); |
| 781 UpdateSignalStrength(); |
| 782 } |
| 783 |
| 784 void NetworkQualityEstimator::UpdateSignalStrength() { |
| 785 #if defined(OS_ANDROID) |
| 786 int32_t signal_strength_dbm; |
| 787 if (!android::cellular_signal_strength::GetSignalStrengthDbm( |
| 788 &signal_strength_dbm)) { |
| 789 return; |
| 790 } |
| 791 min_signal_strength_since_connection_change_ = std::min( |
| 792 min_signal_strength_since_connection_change_, signal_strength_dbm); |
| 793 max_signal_strength_since_connection_change_ = std::max( |
| 794 max_signal_strength_since_connection_change_, signal_strength_dbm); |
| 795 #endif // OS_ANDROID |
| 765 } | 796 } |
| 766 | 797 |
| 767 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { | 798 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { |
| 768 DCHECK(thread_checker_.CalledOnValidThread()); | 799 DCHECK(thread_checker_.CalledOnValidThread()); |
| 769 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { | 800 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { |
| 770 base::HistogramBase* rtt_histogram = | 801 base::HistogramBase* rtt_histogram = |
| 771 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); | 802 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); |
| 772 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); | 803 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); |
| 773 } | 804 } |
| 774 | 805 |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1391 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1361 DCHECK(thread_checker_.CalledOnValidThread()); | 1392 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1362 | 1393 |
| 1363 // TODO(tbansal): Add hysteresis in the notification. | 1394 // TODO(tbansal): Add hysteresis in the notification. |
| 1364 FOR_EACH_OBSERVER( | 1395 FOR_EACH_OBSERVER( |
| 1365 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1396 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1366 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1397 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1367 } | 1398 } |
| 1368 | 1399 |
| 1369 } // namespace net | 1400 } // namespace net |
| OLD | NEW |