xref: /aosp_15_r20/external/cronet/net/nqe/observation_buffer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_NQE_OBSERVATION_BUFFER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_NQE_OBSERVATION_BUFFER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <map>
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <optional>
13*6777b538SAndroid Build Coastguard Worker #include <set>
14*6777b538SAndroid Build Coastguard Worker #include <vector>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/time/tick_clock.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator_util.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_observation.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_observation_source.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker class TimeTicks;
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker }  // namespace base
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker namespace net {
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker class NetworkQualityEstimatorParams;
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker namespace nqe::internal {
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker struct WeightedObservation;
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // Stores observations sorted by time and provides utility functions for
39*6777b538SAndroid Build Coastguard Worker // computing weighted and non-weighted summary statistics.
40*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE ObservationBuffer {
41*6777b538SAndroid Build Coastguard Worker  public:
42*6777b538SAndroid Build Coastguard Worker   ObservationBuffer(const NetworkQualityEstimatorParams* params,
43*6777b538SAndroid Build Coastguard Worker                     const base::TickClock* tick_clock,
44*6777b538SAndroid Build Coastguard Worker                     double weight_multiplier_per_second,
45*6777b538SAndroid Build Coastguard Worker                     double weight_multiplier_per_signal_level);
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker   //  This constructor does not copy the |observations_| from |other| to |this|.
48*6777b538SAndroid Build Coastguard Worker   //  As such, this constructor should only be called before adding any
49*6777b538SAndroid Build Coastguard Worker   //  observations to |other|.
50*6777b538SAndroid Build Coastguard Worker   ObservationBuffer(const ObservationBuffer& other);
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker   ObservationBuffer& operator=(const ObservationBuffer&) = delete;
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   ~ObservationBuffer();
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker   // Adds |observation| to the buffer. The oldest observation in the buffer
57*6777b538SAndroid Build Coastguard Worker   // will be evicted to make room if the buffer is already full.
58*6777b538SAndroid Build Coastguard Worker   void AddObservation(const Observation& observation);
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   // Returns the number of observations in this buffer.
Size()61*6777b538SAndroid Build Coastguard Worker   size_t Size() const { return static_cast<size_t>(observations_.size()); }
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker   // Returns the capacity of this buffer.
64*6777b538SAndroid Build Coastguard Worker   size_t Capacity() const;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   // Clears the observations stored in this buffer.
Clear()67*6777b538SAndroid Build Coastguard Worker   void Clear() { observations_.clear(); }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   // Returns true iff the |percentile| value of the observations in this
70*6777b538SAndroid Build Coastguard Worker   // buffer is available. Sets |result| to the computed |percentile|
71*6777b538SAndroid Build Coastguard Worker   // value of all observations made on or after |begin_timestamp|. If the
72*6777b538SAndroid Build Coastguard Worker   // value is unavailable, false is returned and |result| is not modified.
73*6777b538SAndroid Build Coastguard Worker   // Percentile value is unavailable if all the values in observation buffer are
74*6777b538SAndroid Build Coastguard Worker   // older than |begin_timestamp|. |current_signal_strength| is the current
75*6777b538SAndroid Build Coastguard Worker   // signal strength. |result| must not be null. If |observations_count| is not
76*6777b538SAndroid Build Coastguard Worker   // null, then it is set to the number of observations that were available
77*6777b538SAndroid Build Coastguard Worker   // in the observation buffer for computing the percentile.
78*6777b538SAndroid Build Coastguard Worker   std::optional<int32_t> GetPercentile(base::TimeTicks begin_timestamp,
79*6777b538SAndroid Build Coastguard Worker                                        int32_t current_signal_strength,
80*6777b538SAndroid Build Coastguard Worker                                        int percentile,
81*6777b538SAndroid Build Coastguard Worker                                        size_t* observations_count) const;
82*6777b538SAndroid Build Coastguard Worker 
SetTickClockForTesting(const base::TickClock * tick_clock)83*6777b538SAndroid Build Coastguard Worker   void SetTickClockForTesting(const base::TickClock* tick_clock) {
84*6777b538SAndroid Build Coastguard Worker     tick_clock_ = tick_clock;
85*6777b538SAndroid Build Coastguard Worker   }
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker   // Removes all observations from the buffer whose corresponding entry in
88*6777b538SAndroid Build Coastguard Worker   // |deleted_observation_sources| is set to true. For example, if index 1 and
89*6777b538SAndroid Build Coastguard Worker   // 3 in |deleted_observation_sources| are set to true, then all observations
90*6777b538SAndroid Build Coastguard Worker   // in the buffer that have source set to either 1 or 3 would be removed.
91*6777b538SAndroid Build Coastguard Worker   void RemoveObservationsWithSource(
92*6777b538SAndroid Build Coastguard Worker       bool deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_MAX]);
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker  private:
95*6777b538SAndroid Build Coastguard Worker   // Computes the weighted observations and stores them in
96*6777b538SAndroid Build Coastguard Worker   // |weighted_observations| sorted by ascending |WeightedObservation.value|.
97*6777b538SAndroid Build Coastguard Worker   // Only the observations with timestamp later than |begin_timestamp| are
98*6777b538SAndroid Build Coastguard Worker   // considered. |current_signal_strength| is the current signal strength
99*6777b538SAndroid Build Coastguard Worker   // when the observation was taken. This method also sets |total_weight| to
100*6777b538SAndroid Build Coastguard Worker   // the total weight of all observations. Should be called only when there is
101*6777b538SAndroid Build Coastguard Worker   // at least one observation in the buffer.
102*6777b538SAndroid Build Coastguard Worker   void ComputeWeightedObservations(
103*6777b538SAndroid Build Coastguard Worker       const base::TimeTicks& begin_timestamp,
104*6777b538SAndroid Build Coastguard Worker       int32_t current_signal_strength,
105*6777b538SAndroid Build Coastguard Worker       std::vector<WeightedObservation>* weighted_observations,
106*6777b538SAndroid Build Coastguard Worker       double* total_weight) const;
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   raw_ptr<const NetworkQualityEstimatorParams> params_;
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   // Holds observations sorted by time, with the oldest observation at the
111*6777b538SAndroid Build Coastguard Worker   // front of the queue.
112*6777b538SAndroid Build Coastguard Worker   base::circular_deque<Observation> observations_;
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker   // The factor by which the weight of an observation reduces every second.
115*6777b538SAndroid Build Coastguard Worker   // For example, if an observation is 6 seconds old, its weight would be:
116*6777b538SAndroid Build Coastguard Worker   //     weight_multiplier_per_second_ ^ 6
117*6777b538SAndroid Build Coastguard Worker   // Calculated from |kHalfLifeSeconds| by solving the following equation:
118*6777b538SAndroid Build Coastguard Worker   //     weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
119*6777b538SAndroid Build Coastguard Worker   const double weight_multiplier_per_second_;
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   // The factor by which the weight of an observation reduces for every unit
122*6777b538SAndroid Build Coastguard Worker   // difference in the current signal strength, and the signal strength at
123*6777b538SAndroid Build Coastguard Worker   // which the observation was taken.
124*6777b538SAndroid Build Coastguard Worker   // For example, if the observation was taken at 1 unit, and current signal
125*6777b538SAndroid Build Coastguard Worker   // strength is 4 units, the weight of the observation would be:
126*6777b538SAndroid Build Coastguard Worker   // |weight_multiplier_per_signal_level_| ^ 3.
127*6777b538SAndroid Build Coastguard Worker   const double weight_multiplier_per_signal_level_;
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker   raw_ptr<const base::TickClock> tick_clock_;
130*6777b538SAndroid Build Coastguard Worker };
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker }  // namespace nqe::internal
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker }  // namespace net
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker #endif  // NET_NQE_OBSERVATION_BUFFER_H_
137