| 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 RecordMetricsOnConnectionTypeChanged(); | 666 RecordMetricsOnConnectionTypeChanged(); |
| 663 | 667 |
| 664 // Write the estimates of the previous network to the cache. | 668 // Write the estimates of the previous network to the cache. |
| 665 CacheNetworkQualityEstimate(); | 669 CacheNetworkQualityEstimate(); |
| 666 | 670 |
| 667 // Clear the local state. | 671 // Clear the local state. |
| 668 last_connection_change_ = tick_clock_->NowTicks(); | 672 last_connection_change_ = tick_clock_->NowTicks(); |
| 669 peak_network_quality_ = nqe::internal::NetworkQuality(); | 673 peak_network_quality_ = nqe::internal::NetworkQuality(); |
| 670 downstream_throughput_kbps_observations_.Clear(); | 674 downstream_throughput_kbps_observations_.Clear(); |
| 671 rtt_observations_.Clear(); | 675 rtt_observations_.Clear(); |
| 676 |
| 677 #if defined(OS_ANDROID) |
| 678 if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) { |
| 679 UMA_HISTOGRAM_BOOLEAN( |
| 680 "NQE.CellularSignalStrengthAvailable", |
| 681 min_signal_strength_since_connection_change_ != INT32_MAX && |
| 682 max_signal_strength_since_connection_change_ != INT32_MIN); |
| 683 } |
| 684 #endif // OS_ANDROID |
| 685 min_signal_strength_since_connection_change_ = INT32_MAX; |
| 686 max_signal_strength_since_connection_change_ = INT32_MIN; |
| 687 |
| 672 current_network_id_ = GetCurrentNetworkID(); | 688 current_network_id_ = GetCurrentNetworkID(); |
| 673 | 689 |
| 674 // Query the external estimate provider on certain connection types. Once the | 690 // Query the external estimate provider on certain connection types. Once the |
| 675 // updated estimates are available, OnUpdatedEstimateAvailable will be called | 691 // updated estimates are available, OnUpdatedEstimateAvailable will be called |
| 676 // by |external_estimate_provider_| with updated estimates. | 692 // by |external_estimate_provider_| with updated estimates. |
| 677 if (external_estimate_provider_ && | 693 if (external_estimate_provider_ && |
| 678 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && | 694 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && |
| 679 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && | 695 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && |
| 680 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && | 696 current_network_id_.type != NetworkChangeNotifier::CONNECTION_ETHERNET && |
| 681 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { | 697 current_network_id_.type != NetworkChangeNotifier::CONNECTION_BLUETOOTH) { |
| 682 RecordExternalEstimateProviderMetrics( | 698 RecordExternalEstimateProviderMetrics( |
| 683 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); | 699 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); |
| 684 external_estimate_provider_->Update(); | 700 external_estimate_provider_->Update(); |
| 685 } | 701 } |
| 686 | 702 |
| 687 // Read any cached estimates for the new network. If cached estimates are | 703 // Read any cached estimates for the new network. If cached estimates are |
| 688 // unavailable, add the default estimates. | 704 // unavailable, add the default estimates. |
| 689 if (!ReadCachedNetworkQualityEstimate()) | 705 if (!ReadCachedNetworkQualityEstimate()) |
| 690 AddDefaultEstimates(); | 706 AddDefaultEstimates(); |
| 691 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); | 707 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); |
| 692 throughput_analyzer_->OnConnectionTypeChanged(); | 708 throughput_analyzer_->OnConnectionTypeChanged(); |
| 693 MaybeRecomputeEffectiveConnectionType(); | 709 MaybeRecomputeEffectiveConnectionType(); |
| 710 UpdateSignalStrength(); |
| 711 } |
| 712 |
| 713 void NetworkQualityEstimator::UpdateSignalStrength() { |
| 714 #if defined(OS_ANDROID) |
| 715 int32_t signal_strength_dbm; |
| 716 if (!android::cellular_signal_strength::GetSignalStrengthDbm( |
| 717 &signal_strength_dbm)) { |
| 718 return; |
| 719 } |
| 720 min_signal_strength_since_connection_change_ = std::min( |
| 721 min_signal_strength_since_connection_change_, signal_strength_dbm); |
| 722 max_signal_strength_since_connection_change_ = std::max( |
| 723 max_signal_strength_since_connection_change_, signal_strength_dbm); |
| 724 #endif // OS_ANDROID |
| 694 } | 725 } |
| 695 | 726 |
| 696 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { | 727 void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const { |
| 697 DCHECK(thread_checker_.CalledOnValidThread()); | 728 DCHECK(thread_checker_.CalledOnValidThread()); |
| 698 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { | 729 if (peak_network_quality_.http_rtt() != nqe::internal::InvalidRTT()) { |
| 699 base::HistogramBase* rtt_histogram = | 730 base::HistogramBase* rtt_histogram = |
| 700 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); | 731 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); |
| 701 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); | 732 rtt_histogram->Add(peak_network_quality_.http_rtt().InMilliseconds()); |
| 702 } | 733 } |
| 703 | 734 |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1320 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1290 DCHECK(thread_checker_.CalledOnValidThread()); | 1321 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1291 | 1322 |
| 1292 // TODO(tbansal): Add hysteresis in the notification. | 1323 // TODO(tbansal): Add hysteresis in the notification. |
| 1293 FOR_EACH_OBSERVER( | 1324 FOR_EACH_OBSERVER( |
| 1294 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1325 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1295 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1326 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1296 } | 1327 } |
| 1297 | 1328 |
| 1298 } // namespace net | 1329 } // namespace net |
| OLD | NEW |