xref: /aosp_15_r20/external/cronet/net/nqe/network_quality_estimator.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_
6 #define NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <optional>
13 #include <vector>
14 
15 #include "base/gtest_prod_util.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/observer_list.h"
19 #include "base/sequence_checker.h"
20 #include "base/time/time.h"
21 #include "build/build_config.h"
22 #include "build/chromeos_buildflags.h"
23 #include "net/base/net_export.h"
24 #include "net/base/network_change_notifier.h"
25 #include "net/log/net_log_with_source.h"
26 #include "net/nqe/cached_network_quality.h"
27 #include "net/nqe/effective_connection_type.h"
28 #include "net/nqe/effective_connection_type_observer.h"
29 #include "net/nqe/event_creator.h"
30 #include "net/nqe/network_id.h"
31 #include "net/nqe/network_quality.h"
32 #include "net/nqe/network_quality_estimator_params.h"
33 #include "net/nqe/network_quality_observation.h"
34 #include "net/nqe/network_quality_observation_source.h"
35 #include "net/nqe/network_quality_store.h"
36 #include "net/nqe/observation_buffer.h"
37 #include "net/nqe/peer_to_peer_connections_count_observer.h"
38 #include "net/nqe/rtt_throughput_estimates_observer.h"
39 #include "net/nqe/socket_watcher_factory.h"
40 
41 namespace base {
42 class TickClock;
43 }  // namespace base
44 
45 namespace net {
46 
47 class HostPortPair;
48 class NetLog;
49 
50 namespace nqe::internal {
51 class ThroughputAnalyzer;
52 }  // namespace nqe::internal
53 
54 class URLRequest;
55 
56 // NetworkQualityEstimator provides network quality estimates (quality of the
57 // full paths to all origins that have been connected to).
58 // The estimates are based on the observed organic traffic.
59 // A NetworkQualityEstimator instance is attached to URLRequestContexts and
60 // observes the traffic of URLRequests spawned from the URLRequestContexts.
61 // A single instance of NQE can be attached to multiple URLRequestContexts,
62 // thereby increasing the single NQE instance's accuracy by providing more
63 // observed traffic characteristics.
64 class NET_EXPORT_PRIVATE NetworkQualityEstimator
65     : public NetworkChangeNotifier::ConnectionTypeObserver {
66  public:
67   // Observes measurements of round trip time.
68   class NET_EXPORT_PRIVATE RTTObserver {
69    public:
70     RTTObserver(const RTTObserver&) = delete;
71     RTTObserver& operator=(const RTTObserver&) = delete;
72 
73     // Will be called when a new RTT observation is available. The round trip
74     // time is specified in milliseconds. The time when the observation was
75     // taken and the source of the observation are provided.
76     virtual void OnRTTObservation(int32_t rtt_ms,
77                                   const base::TimeTicks& timestamp,
78                                   NetworkQualityObservationSource source) = 0;
79 
80    protected:
81     RTTObserver() = default;
82     virtual ~RTTObserver() = default;
83   };
84 
85   // Observes measurements of throughput.
86   class NET_EXPORT_PRIVATE ThroughputObserver {
87    public:
88     ThroughputObserver(const ThroughputObserver&) = delete;
89     ThroughputObserver& operator=(const ThroughputObserver&) = delete;
90 
91     // Will be called when a new throughput observation is available.
92     // Throughput is specified in kilobits per second.
93     virtual void OnThroughputObservation(
94         int32_t throughput_kbps,
95         const base::TimeTicks& timestamp,
96         NetworkQualityObservationSource source) = 0;
97 
98    protected:
99     ThroughputObserver() = default;
100     virtual ~ThroughputObserver() = default;
101   };
102 
103   // Creates a new NetworkQualityEstimator.
104   // |params| contains the
105   // configuration parameters relevant to network quality estimator. The caller
106   // must guarantee that |net_log| outlives |this|.
107   NetworkQualityEstimator(
108       std::unique_ptr<NetworkQualityEstimatorParams> params,
109       NetLog* net_log);
110 
111   NetworkQualityEstimator(const NetworkQualityEstimator&) = delete;
112   NetworkQualityEstimator& operator=(const NetworkQualityEstimator&) = delete;
113 
114   ~NetworkQualityEstimator() override;
115 
116   // Returns the current effective connection type.  The effective connection
117   // type is computed by the network quality estimator at regular intervals and
118   // at certain events (e.g., connection change). Virtualized for testing.
119   virtual EffectiveConnectionType GetEffectiveConnectionType() const;
120 
121   // Adds |observer| to a list of effective connection type observers.
122   // The observer must register and unregister itself on the same thread.
123   // |observer| would be notified on the thread on which it registered.
124   // |observer| would be notified of the current effective connection
125   // type in the next message pump.
126   void AddEffectiveConnectionTypeObserver(
127       EffectiveConnectionTypeObserver* observer);
128 
129   // Removes |observer| from a list of effective connection type observers.
130   void RemoveEffectiveConnectionTypeObserver(
131       EffectiveConnectionTypeObserver* observer);
132 
133   // Adds/Removes |observer| from the list of peer to peer connections count
134   // observers. The observer must register and unregister itself on the same
135   // thread. |observer| would be notified on the thread on which it registered.
136   // |observer| would be notified of the current count of peer to peer
137   // connections in the next message pump.
138   void AddPeerToPeerConnectionsCountObserver(
139       PeerToPeerConnectionsCountObserver* observer);
140   void RemovePeerToPeerConnectionsCountObserver(
141       PeerToPeerConnectionsCountObserver* observer);
142 
143   // Returns the current HTTP RTT estimate. If the estimate is unavailable,
144   // the returned optional value is null. The RTT at the HTTP layer measures the
145   // time from when the request was sent (this happens after the connection is
146   // established) to the time when the response headers were received.
147   // Virtualized for testing.
148   virtual std::optional<base::TimeDelta> GetHttpRTT() const;
149 
150   // Returns the current transport RTT estimate. If the estimate is
151   // unavailable, the returned optional value is null.  The RTT at the transport
152   // layer provides an aggregate estimate of the transport RTT as computed by
153   // various underlying TCP and QUIC connections. Virtualized for testing.
154   virtual std::optional<base::TimeDelta> GetTransportRTT() const;
155 
156   // Returns the current downstream throughput estimate (in kilobits per
157   // second). If the estimate is unavailable, the returned optional value is
158   // null.
159   std::optional<int32_t> GetDownstreamThroughputKbps() const;
160 
161   // Adds |observer| to the list of RTT and throughput estimate observers.
162   // The observer must register and unregister itself on the same thread.
163   // |observer| would be notified on the thread on which it registered.
164   // |observer| would be notified of the current values in the next message
165   // pump.
166   void AddRTTAndThroughputEstimatesObserver(
167       RTTAndThroughputEstimatesObserver* observer);
168 
169   // Removes |observer| from the list of RTT and throughput estimate
170   // observers.
171   void RemoveRTTAndThroughputEstimatesObserver(
172       RTTAndThroughputEstimatesObserver* observer);
173 
174   // Notifies NetworkQualityEstimator that the response header of |request| has
175   // been received. Reports the total prefilter network bytes that have been
176   // read for the response of |request|.
177   void NotifyHeadersReceived(const URLRequest& request,
178                              int64_t prefilter_total_bytes_read);
179 
180   // Notifies NetworkQualityEstimator that unfiltered bytes have been read for
181   // |request|. Reports the total prefilter network bytes that have been read
182   // for the response of |request|.
183   void NotifyBytesRead(const URLRequest& request,
184                        int64_t prefilter_total_bytes_read);
185 
186   // Notifies NetworkQualityEstimator that the headers of |request| are about to
187   // be sent.
188   void NotifyStartTransaction(const URLRequest& request);
189 
190   // Notifies NetworkQualityEstimator that the response body of |request| has
191   // been received.
192   void NotifyRequestCompleted(const URLRequest& request);
193 
194   // Notifies NetworkQualityEstimator that |request| will be destroyed.
195   void NotifyURLRequestDestroyed(const URLRequest& request);
196 
197   // Adds |rtt_observer| to the list of round trip time observers. Must be
198   // called on the IO thread.
199   void AddRTTObserver(RTTObserver* rtt_observer);
200 
201   // Removes |rtt_observer| from the list of round trip time observers if it
202   // is on the list of observers. Must be called on the IO thread.
203   void RemoveRTTObserver(RTTObserver* rtt_observer);
204 
205   // Adds |throughput_observer| to the list of throughput observers. Must be
206   // called on the IO thread.
207   void AddThroughputObserver(ThroughputObserver* throughput_observer);
208 
209   // Removes |throughput_observer| from the list of throughput observers if it
210   // is on the list of observers. Must be called on the IO thread.
211   void RemoveThroughputObserver(ThroughputObserver* throughput_observer);
212 
213   SocketPerformanceWatcherFactory* GetSocketPerformanceWatcherFactory();
214 
215   // |use_localhost_requests| should only be true when testing against local
216   // HTTP server and allows the requests to local host to be used for network
217   // quality estimation.
218   void SetUseLocalHostRequestsForTesting(bool use_localhost_requests);
219 
220   // |use_small_responses| should only be true when testing.
221   // Allows the responses smaller than |kMinTransferSizeInBits| to be used for
222   // network quality estimation.
223   void SetUseSmallResponsesForTesting(bool use_small_responses);
224 
225   // If |disable_offline_check| is set to true, then the device offline check is
226   // disabled when computing the effective connection type or when writing the
227   // prefs.
228   void DisableOfflineCheckForTesting(bool disable_offline_check);
229 
230   // Reports |effective_connection_type| to all
231   // EffectiveConnectionTypeObservers.
232   void ReportEffectiveConnectionTypeForTesting(
233       EffectiveConnectionType effective_connection_type);
234 
235   // Reports the RTTs and throughput to all RTTAndThroughputEstimatesObservers.
236   void ReportRTTsAndThroughputForTesting(base::TimeDelta http_rtt,
237                                          base::TimeDelta transport_rtt,
238                                          int32_t downstream_throughput_kbps);
239 
240   // Adds and removes |observer| from the list of cache observers.
241   void AddNetworkQualitiesCacheObserver(
242       nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
243           observer);
244   void RemoveNetworkQualitiesCacheObserver(
245       nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
246           observer);
247 
248   // Called when the persistent prefs have been read. |read_prefs| contains the
249   // parsed prefs as a map between NetworkIDs and CachedNetworkQualities.
250   void OnPrefsRead(
251       const std::map<nqe::internal::NetworkID,
252                      nqe::internal::CachedNetworkQuality> read_prefs);
253 
params()254   const NetworkQualityEstimatorParams* params() { return params_.get(); }
255 
256 #if BUILDFLAG(IS_CHROMEOS_ASH)
257   // Enables getting the network id asynchronously when
258   // GatherEstimatesForNextConnectionType(). This should always be called in
259   // production, because getting the network id involves a blocking call to
260   // recv() in AddressTrackerLinux, and the IO thread should never be blocked.
261   // TODO(https://crbug.com/821607): Remove after the bug is resolved.
262   void EnableGetNetworkIdAsynchronously();
263 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
264 
265   // Forces the effective connection type to be recomputed as |type|. Once
266   // called, effective connection type would always be computed as |type|.
267   // Calling this also notifies all the observers of the effective connection
268   // type as |type|.
269   void SimulateNetworkQualityChangeForTesting(
270       net::EffectiveConnectionType type);
271 
272   // Notifies |this| of round trip ping latency reported by H2 connections.
273   virtual void RecordSpdyPingLatency(const HostPortPair& host_port_pair,
274                                      base::TimeDelta rtt);
275 
276   // Sets the current count of media connections that require low latency.
277   void OnPeerToPeerConnectionsCountChange(uint32_t count);
278 
279   // Returns the current count of peer to peer connections that may require low
280   // latency.
281   uint32_t GetPeerToPeerConnectionsCountChange() const;
282 
283   // Forces NetworkQualityEstimator reports
284   // NetworkChangeNotifier::CONNECTION_WIFI(2) as
285   // EFFECTIVE_CONNECTION_TYPE_SLOW_2G(2) since EffectiveConnectionType and the
286   // production receivers doesn't notice Wifi.
287   void ForceReportWifiAsSlow2GForTesting();
288 
289   typedef nqe::internal::Observation Observation;
290   typedef nqe::internal::ObservationBuffer ObservationBuffer;
291 
292  protected:
293   // NetworkChangeNotifier::ConnectionTypeObserver implementation:
294   void OnConnectionTypeChanged(
295       NetworkChangeNotifier::ConnectionType type) override;
296 
297   // Returns true if median RTT across all samples that belong to
298   // |observation_category| is available and sets |rtt| to the median of RTT
299   // observations since |start_time|. Virtualized for testing. |rtt| should not
300   // be null. If |observations_count| is not null, then it is set to the number
301   // of RTT observations that were used for computing the RTT estimate.
302   [[nodiscard]] virtual bool GetRecentRTT(
303       nqe::internal::ObservationCategory observation_category,
304       const base::TimeTicks& start_time,
305       base::TimeDelta* rtt,
306       size_t* observations_count) const;
307 
308   // Returns true if median downstream throughput is available and sets |kbps|
309   // to the median of downstream throughput (in kilobits per second)
310   // observations since |start_time|. Virtualized for testing. |kbps|
311   // should not be null. Virtualized for testing.
312   // TODO(tbansal): Change it to return throughput as int32.
313   [[nodiscard]] virtual bool GetRecentDownlinkThroughputKbps(
314       const base::TimeTicks& start_time,
315       int32_t* kbps) const;
316 
317   // Overrides the tick clock used by |this| for testing.
318   void SetTickClockForTesting(const base::TickClock* tick_clock);
319 
320   // Returns the effective type of the current connection based on the
321   // samples observed. May use HTTP RTT, transport RTT and
322   // downstream throughput to compute the effective connection type based on
323   // |http_rtt_metric|, |transport_rtt_metric| and
324   // |downstream_throughput_kbps_metric|, respectively. |http_rtt|,
325   // |transport_rtt| and |downstream_throughput_kbps| must be non-null.
326   // |http_rtt|, |transport_rtt| and |downstream_throughput_kbps| are
327   // set to the expected HTTP RTT, transport RTT and downstream throughput (in
328   // kilobits per second) based on observations taken since |start_time|.
329   // If |transport_rtt_observation_count| is not null, then it is set to the
330   // number of transport RTT observations that were available when computing the
331   // effective connection type.
332   virtual EffectiveConnectionType GetRecentEffectiveConnectionTypeUsingMetrics(
333       base::TimeDelta* http_rtt,
334       base::TimeDelta* transport_rtt,
335       base::TimeDelta* end_to_end_rtt,
336       int32_t* downstream_throughput_kbps,
337       size_t* transport_rtt_observation_count,
338       size_t* end_to_end_rtt_observation_count) const;
339 
340   // Notifies |this| of a new transport layer RTT. Called by socket watchers.
341   // Protected for testing.
342   void OnUpdatedTransportRTTAvailable(
343       SocketPerformanceWatcherFactory::Protocol protocol,
344       const base::TimeDelta& rtt,
345       const std::optional<nqe::internal::IPHash>& host);
346 
347   // Returns an estimate of network quality at the specified |percentile|.
348   // Only the observations later than |start_time| are taken into account.
349   // |percentile| must be between 0 and 100 (both inclusive) with higher
350   // percentiles indicating less performant networks. For example, if
351   // |percentile| is 90, then the network is expected to be faster than the
352   // returned estimate with 0.9 probability. Similarly, network is expected to
353   // be slower than the returned estimate with 0.1 probability.
354   // Virtualized for testing.
355   // |observation_category| is the category of observations which should be used
356   // for computing the RTT estimate.
357   // If |observations_count| is not null, then it is set to the number of RTT
358   // observations that were available when computing the RTT estimate.
359   virtual base::TimeDelta GetRTTEstimateInternal(
360       base::TimeTicks start_time,
361       nqe::internal::ObservationCategory observation_category,
362       int percentile,
363       size_t* observations_count) const;
364   int32_t GetDownlinkThroughputKbpsEstimateInternal(
365       const base::TimeTicks& start_time,
366       int percentile) const;
367 
368   // Notifies the observers of RTT or throughput estimates computation.
369   virtual void NotifyObserversOfRTTOrThroughputComputed() const;
370 
371   // Notifies |observer| of the current RTT and throughput if |observer| is
372   // still registered as an observer.
373   virtual void NotifyRTTAndThroughputEstimatesObserverIfPresent(
374       RTTAndThroughputEstimatesObserver* observer) const;
375 
376   // Adds |observation| to the buffer of RTT observations, and notifies RTT
377   // observers of |observation|. May also trigger recomputation of effective
378   // connection type.
379   void AddAndNotifyObserversOfRTT(const Observation& observation);
380 
381   // Adds |observation| to the buffer of throughput observations, and notifies
382   // throughput observers of |observation|. May also trigger recomputation of
383   // effective connection type.
384   void AddAndNotifyObserversOfThroughput(const Observation& observation);
385 
386   // Returns true if the request with observed HTTP of |observed_http_rtt| is
387   // expected to be a hanging request. The decision is made by comparing
388   // |observed_http_rtt| with the expected HTTP and transport RTT.
389   bool IsHangingRequest(base::TimeDelta observed_http_rtt) const;
390 
391   // Forces computation of effective connection type, and notifies observers
392   // if there is a change in its value.
393   void ComputeEffectiveConnectionType();
394 
395   // Returns a non-null value if the value of the effective connection type has
396   // been overridden for testing.
397   virtual std::optional<net::EffectiveConnectionType> GetOverrideECT() const;
398 
399   // Observer list for RTT or throughput estimates. Protected for testing.
400   base::ObserverList<RTTAndThroughputEstimatesObserver>::Unchecked
401       rtt_and_throughput_estimates_observer_list_;
402 
403   // Observer list for changes in effective connection type.
404   base::ObserverList<EffectiveConnectionTypeObserver>::Unchecked
405       effective_connection_type_observer_list_;
406 
407   // Observer list for changes in peer to peer connections count.
408   base::ObserverList<PeerToPeerConnectionsCountObserver>::Unchecked
409       peer_to_peer_type_observer_list_;
410 
411   // Params to configure the network quality estimator.
412   const std::unique_ptr<NetworkQualityEstimatorParams> params_;
413 
414   // Number of end to end RTT samples available when the ECT was last computed.
415   size_t end_to_end_rtt_observation_count_at_last_ect_computation_ = 0;
416 
417   // Current count of active peer to peer connections.
418   uint32_t p2p_connections_count_ = 0u;
419 
420  private:
421   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
422                            AdaptiveRecomputationEffectiveConnectionType);
423   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
424   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
425   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
426                            DefaultObservationsOverridden);
427   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles);
428   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMetricsSince);
429   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
430                            UnknownEffectiveConnectionType);
431   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
432                            TypicalNetworkQualities);
433   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
434                            OnPrefsReadWithReadingDisabled);
435   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
436                            ForceEffectiveConnectionTypeThroughFieldTrial);
437   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
438                            ObservationDiscardedIfCachedEstimateAvailable);
439   FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
440                            TestRttThroughputObservers);
441 
442   // Returns the RTT value to be used when the valid RTT is unavailable. Readers
443   // should discard RTT if it is set to the value returned by |InvalidRTT()|.
444   static const base::TimeDelta InvalidRTT();
445 
446   // Records a downstream throughput observation to the observation buffer if
447   // a valid observation is available. |downstream_kbps| is the downstream
448   // throughput in kilobits per second.
449   void OnNewThroughputObservationAvailable(int32_t downstream_kbps);
450 
451   // Adds the default median RTT and downstream throughput estimate for the
452   // current connection type to the observation buffer.
453   void AddDefaultEstimates();
454 
455   // Returns the current network ID checking by calling the platform APIs.
456   // Virtualized for testing.
457   virtual nqe::internal::NetworkID GetCurrentNetworkID() const;
458 
459   // Returns true only if the |request| can be used for RTT estimation.
460   bool RequestProvidesRTTObservation(const URLRequest& request) const;
461 
462   // Returns true if ECT should be recomputed.
463   bool ShouldComputeEffectiveConnectionType() const;
464 
465   // Calls ShouldComputeEffectiveConnectionType() to determine if ECT needs to
466   // be computed. If so, it recomputes effective connection type.
467   void MaybeComputeEffectiveConnectionType();
468 
469   // Notifies observers of a change in effective connection type.
470   void NotifyObserversOfEffectiveConnectionTypeChanged();
471 
472   // Notifies |observer| of the current effective connection type if |observer|
473   // is still registered as an observer.
474   void NotifyEffectiveConnectionTypeObserverIfPresent(
475       MayBeDangling<EffectiveConnectionTypeObserver> observer) const;
476 
477   // Notifies |observer| of the current count of peer to peer connections.
478   void NotifyPeerToPeerConnectionsCountObserverIfPresent(
479       MayBeDangling<PeerToPeerConnectionsCountObserver> observer) const;
480 
481   // Records NQE accuracy metrics. |measuring_duration| should belong to the
482   // vector returned by AccuracyRecordingIntervals().
483   // RecordAccuracyAfterMainFrame should be called |measuring_duration| after a
484   // main frame request is observed.
485   void RecordAccuracyAfterMainFrame(base::TimeDelta measuring_duration) const;
486 
487   // Updates the provided |http_rtt| based on all provided RTT values.
488   void UpdateHttpRttUsingAllRttValues(
489       base::TimeDelta* http_rtt,
490       const base::TimeDelta transport_rtt,
491       const base::TimeDelta end_to_end_rtt) const;
492 
493   // Returns true if the cached network quality estimate was successfully read.
494   bool ReadCachedNetworkQualityEstimate();
495 
496   // Gathers metrics for the next connection type. Called when there is a change
497   // in the connection type.
498   void GatherEstimatesForNextConnectionType();
499 
500   // Invoked to continue GatherEstimatesForNextConnectionType work after getting
501   // network id. If |get_network_id_asynchronously_| is set, the network id is
502   // fetched on a worker thread. Otherwise, GatherEstimatesForNextConnectionType
503   // calls this directly. This is a workaround for https://crbug.com/821607
504   // where net::GetWifiSSID() call gets stuck.
505   void ContinueGatherEstimatesForNextConnectionType(
506       const nqe::internal::NetworkID& network_id);
507 
508   // Updates the value of |cached_estimate_applied_| if |observation| is
509   // computed from a cached estimate. |buffer| is the observation buffer to
510   // which the cached estimate is being added to.
511   void MaybeUpdateCachedEstimateApplied(const Observation& observation,
512                                         ObservationBuffer* buffer);
513 
514   // Returns true if |observation| should be added to the observation buffer.
515   bool ShouldAddObservation(const Observation& observation) const;
516 
517   // Returns true if the socket watcher can run the callback to notify the RTT
518   // observations.
519   bool ShouldSocketWatcherNotifyRTT(base::TimeTicks now);
520 
521   // When RTT counts are low, it may be impossible to predict accurate ECT. In
522   // that case, we just give the highest value.
523   void AdjustHttpRttBasedOnRTTCounts(base::TimeDelta* http_rtt) const;
524 
525   // Clamps the throughput estimate based on the current effective connection
526   // type.
527   void ClampKbpsBasedOnEct();
528 
529   // Determines if the requests to local host can be used in estimating the
530   // network quality. Set to true only for tests.
531   bool use_localhost_requests_ = false;
532 
533   // When set to true, the device offline check is disabled when computing the
534   // effective connection type or when writing the prefs. Set to true only for
535   // testing.
536   bool disable_offline_check_ = false;
537 
538   // Tick clock used by the network quality estimator.
539   raw_ptr<const base::TickClock> tick_clock_;
540 
541   // Time when last connection change was observed.
542   base::TimeTicks last_connection_change_;
543 
544   // ID of the current network.
545   nqe::internal::NetworkID current_network_id_;
546 
547   // Buffer that holds throughput observations from the HTTP layer (in kilobits
548   // per second) sorted by timestamp.
549   ObservationBuffer http_downstream_throughput_kbps_observations_;
550 
551   // Buffer that holds RTT observations with different observation categories.
552   // The entries in |rtt_ms_observations_| are in the same order as the
553   // entries in the nqe::internal:ObservationCategory enum.
554   // Each observation buffer in |rtt_ms_observations_| stores RTT observations
555   // in milliseconds. Within a buffer, the observations are sorted by timestamp.
556   ObservationBuffer
557       rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_COUNT];
558 
559   // Observer lists for round trip times and throughput measurements.
560   base::ObserverList<RTTObserver>::Unchecked rtt_observer_list_;
561   base::ObserverList<ThroughputObserver>::Unchecked throughput_observer_list_;
562 
563   std::unique_ptr<nqe::internal::SocketWatcherFactory> watcher_factory_;
564 
565   // Takes throughput measurements, and passes them back to |this| through the
566   // provided callback. |this| stores the throughput observations in
567   // |downstream_throughput_kbps_observations_|, which are later used for
568   // estimating the throughput.
569   std::unique_ptr<nqe::internal::ThroughputAnalyzer> throughput_analyzer_;
570 
571   // Minimum duration between two consecutive computations of effective
572   // connection type. Set to non-zero value as a performance optimization.
573   const base::TimeDelta effective_connection_type_recomputation_interval_ =
574       base::Seconds(10);
575 
576   // Time when the effective connection type was last computed.
577   base::TimeTicks last_effective_connection_type_computation_;
578 
579   // Number of RTT and bandwidth samples available when effective connection
580   // type was last recomputed.
581   size_t rtt_observations_size_at_last_ect_computation_ = 0;
582   size_t throughput_observations_size_at_last_ect_computation_ = 0;
583 
584   // Number of transport RTT samples available when the ECT was last computed.
585   size_t transport_rtt_observation_count_last_ect_computation_ = 0;
586 
587   // Number of RTT observations received since the effective connection type was
588   // last computed.
589   size_t new_rtt_observations_since_last_ect_computation_ = 0;
590 
591   // Number of throughput observations received since the effective connection
592   // type was last computed.
593   size_t new_throughput_observations_since_last_ect_computation_ = 0;
594 
595   // Current estimate of the network quality.
596   nqe::internal::NetworkQuality network_quality_;
597   std::optional<base::TimeDelta> end_to_end_rtt_;
598 
599   // Current effective connection type. It is updated on connection change
600   // events. It is also updated every time there is network traffic (provided
601   // the last computation was more than
602   // |effective_connection_type_recomputation_interval_| ago).
603   EffectiveConnectionType effective_connection_type_ =
604       EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
605 
606   // Stores the qualities of different networks.
607   std::unique_ptr<nqe::internal::NetworkQualityStore> network_quality_store_;
608 
609   // True if a cached RTT or throughput estimate was available and the
610   // corresponding observation has been added on the current network.
611   bool cached_estimate_applied_ = false;
612 
613   SEQUENCE_CHECKER(sequence_checker_);
614 
615   NetLogWithSource net_log_;
616 
617   // Manages the writing of events to the net log.
618   nqe::internal::EventCreator event_creator_;
619 
620   // Time when the last RTT observation from a socket watcher was received.
621   base::TimeTicks last_socket_watcher_rtt_notification_;
622 
623   std::optional<base::TimeTicks> last_signal_strength_check_timestamp_;
624 
625 #if BUILDFLAG(IS_CHROMEOS_ASH)
626   // Whether the network id should be obtained on a worker thread.
627   bool get_network_id_asynchronously_ = false;
628 #endif
629 
630   bool force_report_wifi_as_slow_2g_for_testing_ = false;
631 
632   base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_{this};
633 };
634 
635 }  // namespace net
636 
637 #endif  // NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_
638