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