Chromium Code Reviews| 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/base/network_quality_estimator.h" | 5 #include "net/base/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "build/build_config.h" | |
| 12 #include "net/base/load_timing_info.h" | 14 #include "net/base/load_timing_info.h" |
| 13 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 14 #include "net/base/network_quality.h" | 16 #include "net/base/network_interfaces.h" |
| 15 #include "net/url_request/url_request.h" | 17 #include "net/url_request/url_request.h" |
| 16 #include "url/gurl.h" | 18 #include "url/gurl.h" |
| 17 | 19 |
| 20 #if defined(OS_ANDROID) | |
| 21 #include "net/android/network_library.h" | |
| 22 #endif // OS_ANDROID | |
| 23 | |
| 18 namespace { | 24 namespace { |
| 19 | 25 |
| 20 // Maximum number of observations that can be held in the ObservationBuffer. | 26 // Maximum number of observations that can be held in the ObservationBuffer. |
| 21 const size_t kMaximumObservationsBufferSize = 500; | 27 const size_t kMaximumObservationsBufferSize = 500; |
| 22 | 28 |
| 23 } // namespace | 29 } // namespace |
| 24 | 30 |
| 25 namespace net { | 31 namespace net { |
| 26 | 32 |
| 33 const size_t NetworkQualityEstimator::kMaximumNetworkQualityCacheSize = 10; | |
| 34 | |
| 27 NetworkQualityEstimator::NetworkQualityEstimator() | 35 NetworkQualityEstimator::NetworkQualityEstimator() |
| 28 : NetworkQualityEstimator(false, false) { | 36 : NetworkQualityEstimator(false, false) { |
| 29 } | 37 } |
| 30 | 38 |
| 31 NetworkQualityEstimator::NetworkQualityEstimator( | 39 NetworkQualityEstimator::NetworkQualityEstimator( |
| 32 bool allow_local_host_requests_for_tests, | 40 bool allow_local_host_requests_for_tests, |
| 33 bool allow_smaller_responses_for_tests) | 41 bool allow_smaller_responses_for_tests) |
| 34 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 42 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
| 35 allow_small_responses_(allow_smaller_responses_for_tests), | 43 allow_small_responses_(allow_smaller_responses_for_tests), |
| 36 last_connection_change_(base::TimeTicks::Now()), | 44 last_connection_change_(base::TimeTicks::Now()), |
| 37 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), | 45 current_network_id_( |
| 46 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | |
| 47 std::string())), | |
| 38 fastest_rtt_since_last_connection_change_(base::TimeDelta::Max()), | 48 fastest_rtt_since_last_connection_change_(base::TimeDelta::Max()), |
| 39 peak_kbps_since_last_connection_change_(0) { | 49 peak_kbps_since_last_connection_change_(0) { |
| 40 static_assert(kMinRequestDurationMicroseconds > 0, | 50 static_assert(kMinRequestDurationMicroseconds > 0, |
| 41 "Minimum request duration must be > 0"); | 51 "Minimum request duration must be > 0"); |
| 52 static_assert(kMaximumNetworkQualityCacheSize > 0, | |
| 53 "Size of the network quality cache must be > 0"); | |
| 54 | |
| 55 // This limit should not be increased unless the logic for removing the | |
| 56 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | |
| 57 static_assert(kMaximumNetworkQualityCacheSize <= 10, | |
| 58 "Size of the network quality cache must <= 10"); | |
| 42 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 59 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 60 current_network_id_ = GetCurrentNetworkID(); | |
| 43 } | 61 } |
| 44 | 62 |
| 45 NetworkQualityEstimator::~NetworkQualityEstimator() { | 63 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 46 DCHECK(thread_checker_.CalledOnValidThread()); | 64 DCHECK(thread_checker_.CalledOnValidThread()); |
| 47 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 65 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 48 } | 66 } |
| 49 | 67 |
| 50 void NetworkQualityEstimator::NotifyDataReceived( | 68 void NetworkQualityEstimator::NotifyDataReceived( |
| 51 const URLRequest& request, | 69 const URLRequest& request, |
| 52 int64_t cumulative_prefilter_bytes_read, | 70 int64_t cumulative_prefilter_bytes_read, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 | 147 |
| 130 kbps_observations_.AddObservation(Observation(kbps, now)); | 148 kbps_observations_.AddObservation(Observation(kbps, now)); |
| 131 } | 149 } |
| 132 } | 150 } |
| 133 } | 151 } |
| 134 | 152 |
| 135 void NetworkQualityEstimator::OnConnectionTypeChanged( | 153 void NetworkQualityEstimator::OnConnectionTypeChanged( |
| 136 NetworkChangeNotifier::ConnectionType type) { | 154 NetworkChangeNotifier::ConnectionType type) { |
| 137 DCHECK(thread_checker_.CalledOnValidThread()); | 155 DCHECK(thread_checker_.CalledOnValidThread()); |
| 138 if (fastest_rtt_since_last_connection_change_ != base::TimeDelta::Max()) { | 156 if (fastest_rtt_since_last_connection_change_ != base::TimeDelta::Max()) { |
| 139 switch (current_connection_type_) { | 157 switch (current_network_id_.type) { |
| 140 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 158 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
| 141 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", | 159 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", |
| 142 fastest_rtt_since_last_connection_change_); | 160 fastest_rtt_since_last_connection_change_); |
| 143 break; | 161 break; |
| 144 case NetworkChangeNotifier::CONNECTION_ETHERNET: | 162 case NetworkChangeNotifier::CONNECTION_ETHERNET: |
| 145 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet", | 163 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet", |
| 146 fastest_rtt_since_last_connection_change_); | 164 fastest_rtt_since_last_connection_change_); |
| 147 break; | 165 break; |
| 148 case NetworkChangeNotifier::CONNECTION_WIFI: | 166 case NetworkChangeNotifier::CONNECTION_WIFI: |
| 149 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi", | 167 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi", |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 163 break; | 181 break; |
| 164 case NetworkChangeNotifier::CONNECTION_NONE: | 182 case NetworkChangeNotifier::CONNECTION_NONE: |
| 165 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", | 183 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", |
| 166 fastest_rtt_since_last_connection_change_); | 184 fastest_rtt_since_last_connection_change_); |
| 167 break; | 185 break; |
| 168 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: | 186 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: |
| 169 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", | 187 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", |
| 170 fastest_rtt_since_last_connection_change_); | 188 fastest_rtt_since_last_connection_change_); |
| 171 break; | 189 break; |
| 172 default: | 190 default: |
| 173 NOTREACHED(); | 191 NOTREACHED() << "Unexpected connection type = " |
| 192 << current_network_id_.type; | |
| 174 break; | 193 break; |
| 175 } | 194 } |
| 176 } | 195 } |
| 177 | 196 |
| 178 if (peak_kbps_since_last_connection_change_) { | 197 if (peak_kbps_since_last_connection_change_) { |
| 179 switch (current_connection_type_) { | 198 switch (current_network_id_.type) { |
| 180 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 199 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
| 181 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown", | 200 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown", |
| 182 peak_kbps_since_last_connection_change_); | 201 peak_kbps_since_last_connection_change_); |
| 183 break; | 202 break; |
| 184 case NetworkChangeNotifier::CONNECTION_ETHERNET: | 203 case NetworkChangeNotifier::CONNECTION_ETHERNET: |
| 185 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Ethernet", | 204 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Ethernet", |
| 186 peak_kbps_since_last_connection_change_); | 205 peak_kbps_since_last_connection_change_); |
| 187 break; | 206 break; |
| 188 case NetworkChangeNotifier::CONNECTION_WIFI: | 207 case NetworkChangeNotifier::CONNECTION_WIFI: |
| 189 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Wifi", | 208 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Wifi", |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 203 break; | 222 break; |
| 204 case NetworkChangeNotifier::CONNECTION_NONE: | 223 case NetworkChangeNotifier::CONNECTION_NONE: |
| 205 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None", | 224 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None", |
| 206 peak_kbps_since_last_connection_change_); | 225 peak_kbps_since_last_connection_change_); |
| 207 break; | 226 break; |
| 208 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: | 227 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: |
| 209 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", | 228 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", |
| 210 peak_kbps_since_last_connection_change_); | 229 peak_kbps_since_last_connection_change_); |
| 211 break; | 230 break; |
| 212 default: | 231 default: |
| 213 NOTREACHED(); | 232 NOTREACHED() << "Unexpected connection type = " |
| 233 << current_network_id_.type; | |
| 214 break; | 234 break; |
| 215 } | 235 } |
| 216 } | 236 } |
| 217 | 237 |
| 238 // Write the estimates of the previous network to the cache. | |
| 239 CacheNetworkQualityEstimate(); | |
| 240 | |
| 241 // Clear the local state. | |
| 218 last_connection_change_ = base::TimeTicks::Now(); | 242 last_connection_change_ = base::TimeTicks::Now(); |
| 219 peak_kbps_since_last_connection_change_ = 0; | 243 peak_kbps_since_last_connection_change_ = 0; |
| 220 fastest_rtt_since_last_connection_change_ = base::TimeDelta::Max(); | 244 fastest_rtt_since_last_connection_change_ = base::TimeDelta::Max(); |
| 221 kbps_observations_.Clear(); | 245 kbps_observations_.Clear(); |
| 222 rtt_msec_observations_.Clear(); | 246 rtt_msec_observations_.Clear(); |
| 223 current_connection_type_ = type; | 247 |
| 248 // Update the current network ID. | |
| 249 current_network_id_ = GetCurrentNetworkID(); | |
| 250 | |
| 251 // Read any cached estimates for the new network. | |
| 252 ReadCachedNetworkQualityEstimate(); | |
| 253 } | |
| 254 | |
| 255 size_t NetworkQualityEstimator::GetNetworkQualityCacheSizeForTests() const { | |
| 256 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 257 return cached_network_qualities_.size(); | |
| 224 } | 258 } |
| 225 | 259 |
| 226 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const { | 260 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const { |
| 227 DCHECK(thread_checker_.CalledOnValidThread()); | 261 DCHECK(thread_checker_.CalledOnValidThread()); |
| 228 | 262 |
| 229 return NetworkQuality(fastest_rtt_since_last_connection_change_, | 263 return NetworkQuality(fastest_rtt_since_last_connection_change_, |
| 230 peak_kbps_since_last_connection_change_); | 264 peak_kbps_since_last_connection_change_); |
| 231 } | 265 } |
| 232 | 266 |
| 233 size_t NetworkQualityEstimator::GetMaximumObservationBufferSizeForTests() | 267 size_t NetworkQualityEstimator::GetMaximumObservationBufferSizeForTests() |
| 234 const { | 268 const { |
| 269 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 235 return kMaximumObservationsBufferSize; | 270 return kMaximumObservationsBufferSize; |
| 236 } | 271 } |
| 237 | 272 |
| 238 bool NetworkQualityEstimator::VerifyBufferSizeForTests( | 273 size_t NetworkQualityEstimator::GetKbpsObservationBufferSizeForTests() const { |
| 239 size_t expected_size) const { | 274 DCHECK(thread_checker_.CalledOnValidThread()); |
| 240 return kbps_observations_.Size() == expected_size && | 275 return kbps_observations_.Size(); |
| 241 rtt_msec_observations_.Size() == expected_size; | 276 } |
| 277 | |
| 278 size_t NetworkQualityEstimator::GetRTTObservationBufferSizeForTests() const { | |
| 279 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 280 return rtt_msec_observations_.Size(); | |
| 242 } | 281 } |
| 243 | 282 |
| 244 NetworkQualityEstimator::Observation::Observation(int32_t value, | 283 NetworkQualityEstimator::Observation::Observation(int32_t value, |
| 245 base::TimeTicks timestamp) | 284 base::TimeTicks timestamp) |
| 246 : value(value), timestamp(timestamp) { | 285 : value(value), timestamp(timestamp) { |
| 247 DCHECK_GE(value, 0); | 286 DCHECK_GE(value, 0); |
| 248 DCHECK(!timestamp.is_null()); | 287 DCHECK(!timestamp.is_null()); |
| 249 } | 288 } |
| 250 | 289 |
| 251 NetworkQualityEstimator::Observation::~Observation() { | 290 NetworkQualityEstimator::Observation::~Observation() { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 272 | 311 |
| 273 size_t NetworkQualityEstimator::ObservationBuffer::Size() const { | 312 size_t NetworkQualityEstimator::ObservationBuffer::Size() const { |
| 274 return observations_.size(); | 313 return observations_.size(); |
| 275 } | 314 } |
| 276 | 315 |
| 277 void NetworkQualityEstimator::ObservationBuffer::Clear() { | 316 void NetworkQualityEstimator::ObservationBuffer::Clear() { |
| 278 observations_.clear(); | 317 observations_.clear(); |
| 279 DCHECK(observations_.empty()); | 318 DCHECK(observations_.empty()); |
| 280 } | 319 } |
| 281 | 320 |
| 321 NetworkQualityEstimator::NetworkID | |
| 322 NetworkQualityEstimator::GetCurrentNetworkID() const { | |
| 323 // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class | |
| 324 // that overrides this method on the Android platform. | |
| 325 NetworkQualityEstimator::NetworkID network_id( | |
| 326 NetworkChangeNotifier::GetConnectionType(), std::string()); | |
| 327 | |
| 328 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 329 | |
| 330 switch (network_id.type) { | |
| 331 case NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN: | |
| 332 case NetworkChangeNotifier::ConnectionType::CONNECTION_NONE: | |
| 333 case NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH: | |
| 334 case NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET: | |
| 335 break; | |
| 336 case NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI: | |
| 337 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) | |
| 338 network_id.id = GetWifiSSID(); | |
| 339 break; | |
| 340 #else | |
| 341 break; | |
| 342 #endif | |
| 343 case NetworkChangeNotifier::ConnectionType::CONNECTION_2G: | |
| 344 case NetworkChangeNotifier::ConnectionType::CONNECTION_3G: | |
| 345 case NetworkChangeNotifier::ConnectionType::CONNECTION_4G: | |
| 346 #if defined(OS_ANDROID) | |
| 347 network_id.id = android::GetTelephonyNetworkOperator(); | |
| 348 break; | |
| 349 #else | |
| 350 break; | |
| 351 #endif | |
| 352 default: | |
| 353 NOTREACHED() << "Unexpected connection type = " << network_id.type; | |
| 354 } | |
| 355 // Due to race, it is possible that the connection type changed between when | |
|
pauljensen
2015/06/18 16:20:26
Remove "Due to race, "
tbansal1
2015/06/18 20:57:40
Done.
| |
| 356 // GetCurrentConnectionType() was read and when network name was read. | |
|
pauljensen
2015/06/18 16:20:25
network->the network
pauljensen
2015/06/18 16:20:26
read->called
tbansal1
2015/06/18 20:57:40
Done.
tbansal1
2015/06/18 20:57:40
Done.
| |
| 357 // Check if that happened and retry. | |
|
pauljensen
2015/06/18 16:20:26
Mention that this isn't perfect but should catch t
tbansal1
2015/06/18 20:57:40
Done.
| |
| 358 if (network_id.type != NetworkChangeNotifier::GetConnectionType()) | |
| 359 return GetCurrentNetworkID(); | |
|
pauljensen
2015/06/18 16:20:26
Please use a loop rather than recursion. Waiting
tbansal1
2015/06/18 20:57:41
Using while(true) now, which I found to be slightl
pauljensen
2015/06/19 03:10:07
SGTM
| |
| 360 return network_id; | |
| 361 } | |
| 362 | |
| 363 bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() { | |
| 364 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 365 | |
| 366 CachedNetworkQualities::iterator it = | |
| 367 cached_network_qualities_.find(current_network_id_); | |
| 368 if (it != cached_network_qualities_.end()) { | |
| 369 // TOOD(tbansal): Populate these values back into the median computing | |
| 370 // algorithm. | |
| 371 // Add UMA to record how frequently matches happen. | |
| 372 // Ensure that the estimates read are non-zero before populating them into | |
| 373 // the median computing algorithm. | |
| 374 peak_kbps_since_last_connection_change_ = | |
| 375 it->second->network_quality().downstream_throughput_kbps(); | |
| 376 fastest_rtt_since_last_connection_change_ = | |
| 377 it->second->network_quality().rtt(); | |
| 378 return true; | |
| 379 } | |
| 380 return false; | |
| 381 } | |
| 382 | |
| 383 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | |
| 384 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 385 DCHECK_LE(cached_network_qualities_.size(), kMaximumNetworkQualityCacheSize); | |
| 386 | |
| 387 // TODO(tbansal): The following variables should be initialized using the | |
| 388 // median values reported by the NetworkQualityEstimator. | |
| 389 int median_kbps = peak_kbps_since_last_connection_change_; | |
| 390 base::TimeDelta median_rtt = fastest_rtt_since_last_connection_change_; | |
| 391 | |
| 392 // If this network is already in the cache, overwrite that entry. | |
| 393 CachedNetworkQualities::iterator it = | |
| 394 cached_network_qualities_.find(current_network_id_); | |
| 395 if (it != cached_network_qualities_.end()) { | |
| 396 (it->second)->UpdateNetworkQuality(median_kbps, median_rtt); | |
|
pauljensen
2015/06/19 03:10:07
This in-place update seems odd. Why not just:
c
tbansal1
2015/06/19 23:34:40
For this, I will need to overload = operator for C
pauljensen
2015/06/20 01:30:45
SGTM
pauljensen
2015/06/22 18:39:52
You never implemented this change.
tbansal1
2015/06/22 20:28:25
Took a slightly different approach which allowed m
| |
| 397 return; | |
| 398 } | |
| 399 | |
| 400 if (cached_network_qualities_.size() == kMaximumNetworkQualityCacheSize) { | |
| 401 // Remove the oldest entry. | |
| 402 CachedNetworkQualities::iterator oldest_entry_iterator = | |
| 403 cached_network_qualities_.begin(); | |
| 404 | |
| 405 for (CachedNetworkQualities::iterator it = | |
| 406 cached_network_qualities_.begin(); | |
| 407 it != cached_network_qualities_.end(); ++it) { | |
| 408 if ((it->second)->OlderThan(*(oldest_entry_iterator->second.get()))) | |
| 409 oldest_entry_iterator = it; | |
| 410 } | |
| 411 cached_network_qualities_.erase(oldest_entry_iterator); | |
| 412 } | |
| 413 | |
| 414 DCHECK_LT(cached_network_qualities_.size(), kMaximumNetworkQualityCacheSize); | |
| 415 cached_network_qualities_.insert(std::make_pair( | |
| 416 current_network_id_, make_scoped_ptr(new CachedNetworkQuality( | |
| 417 NetworkQuality(median_rtt, median_kbps))))); | |
| 418 DCHECK_LE(cached_network_qualities_.size(), kMaximumNetworkQualityCacheSize); | |
| 419 } | |
| 420 | |
| 421 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | |
| 422 const NetworkQuality& network_quality) | |
| 423 : last_update_time_(base::TimeTicks::Now()), | |
| 424 network_quality_(network_quality) { | |
| 425 } | |
| 426 | |
| 427 NetworkQualityEstimator::CachedNetworkQuality::~CachedNetworkQuality() { | |
| 428 } | |
| 429 | |
| 430 bool NetworkQualityEstimator::CachedNetworkQuality::OlderThan( | |
| 431 const CachedNetworkQuality& cached_network_quality) const { | |
| 432 return last_update_time_ < cached_network_quality.last_update_time_; | |
| 433 } | |
| 434 | |
| 435 void NetworkQualityEstimator::CachedNetworkQuality::UpdateNetworkQuality( | |
| 436 int32_t median_kbps, | |
| 437 const base::TimeDelta& median_rtt) { | |
| 438 DCHECK_GE(median_kbps, 0); | |
| 439 DCHECK_GE(median_rtt, base::TimeDelta()); | |
| 440 last_update_time_ = base::TimeTicks::Now(); | |
| 441 | |
| 442 network_quality_ = NetworkQuality(median_rtt, median_kbps); | |
| 443 } | |
| 444 | |
| 282 } // namespace net | 445 } // namespace net |
| OLD | NEW |