xref: /aosp_15_r20/external/libchrome/base/metrics/field_trial_params.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_METRICS_FIELD_TRIAL_PARAMS_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_METRICS_FIELD_TRIAL_PARAMS_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <map>
9*635a8641SAndroid Build Coastguard Worker #include <string>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker namespace base {
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker struct Feature;
16*635a8641SAndroid Build Coastguard Worker 
17*635a8641SAndroid Build Coastguard Worker // Associates the specified set of key-value |params| with the field trial
18*635a8641SAndroid Build Coastguard Worker // specified by |trial_name| and |group_name|. Fails and returns false if the
19*635a8641SAndroid Build Coastguard Worker // specified field trial already has params associated with it or the trial
20*635a8641SAndroid Build Coastguard Worker // is already active (group() has been called on it). Thread safe.
21*635a8641SAndroid Build Coastguard Worker BASE_EXPORT bool AssociateFieldTrialParams(
22*635a8641SAndroid Build Coastguard Worker     const std::string& trial_name,
23*635a8641SAndroid Build Coastguard Worker     const std::string& group_name,
24*635a8641SAndroid Build Coastguard Worker     const std::map<std::string, std::string>& params);
25*635a8641SAndroid Build Coastguard Worker 
26*635a8641SAndroid Build Coastguard Worker // Retrieves the set of key-value |params| for the specified field trial, based
27*635a8641SAndroid Build Coastguard Worker // on its selected group. If the field trial does not exist or its selected
28*635a8641SAndroid Build Coastguard Worker // group does not have any parameters associated with it, returns false and
29*635a8641SAndroid Build Coastguard Worker // does not modify |params|. Calling this function will result in the field
30*635a8641SAndroid Build Coastguard Worker // trial being marked as active if found (i.e. group() will be called on it),
31*635a8641SAndroid Build Coastguard Worker // if it wasn't already. Thread safe.
32*635a8641SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParams(
33*635a8641SAndroid Build Coastguard Worker     const std::string& trial_name,
34*635a8641SAndroid Build Coastguard Worker     std::map<std::string, std::string>* params);
35*635a8641SAndroid Build Coastguard Worker 
36*635a8641SAndroid Build Coastguard Worker // Retrieves the set of key-value |params| for the field trial associated with
37*635a8641SAndroid Build Coastguard Worker // the specified |feature|. A feature is associated with at most one field
38*635a8641SAndroid Build Coastguard Worker // trial and selected group. See  base/feature_list.h for more information on
39*635a8641SAndroid Build Coastguard Worker // features. If the feature is not enabled, or if there's no associated params,
40*635a8641SAndroid Build Coastguard Worker // returns false and does not modify |params|. Calling this function will
41*635a8641SAndroid Build Coastguard Worker // result in the associated field trial being marked as active if found (i.e.
42*635a8641SAndroid Build Coastguard Worker // group() will be called on it), if it wasn't already. Thread safe.
43*635a8641SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParamsByFeature(
44*635a8641SAndroid Build Coastguard Worker     const base::Feature& feature,
45*635a8641SAndroid Build Coastguard Worker     std::map<std::string, std::string>* params);
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker // Retrieves a specific parameter value corresponding to |param_name| for the
48*635a8641SAndroid Build Coastguard Worker // specified field trial, based on its selected group. If the field trial does
49*635a8641SAndroid Build Coastguard Worker // not exist or the specified parameter does not exist, returns an empty
50*635a8641SAndroid Build Coastguard Worker // string. Calling this function will result in the field trial being marked as
51*635a8641SAndroid Build Coastguard Worker // active if found (i.e. group() will be called on it), if it wasn't already.
52*635a8641SAndroid Build Coastguard Worker // Thread safe.
53*635a8641SAndroid Build Coastguard Worker BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name,
54*635a8641SAndroid Build Coastguard Worker                                                 const std::string& param_name);
55*635a8641SAndroid Build Coastguard Worker 
56*635a8641SAndroid Build Coastguard Worker // Retrieves a specific parameter value corresponding to |param_name| for the
57*635a8641SAndroid Build Coastguard Worker // field trial associated with the specified |feature|. A feature is associated
58*635a8641SAndroid Build Coastguard Worker // with at most one field trial and selected group. See base/feature_list.h for
59*635a8641SAndroid Build Coastguard Worker // more information on features. If the feature is not enabled, or the
60*635a8641SAndroid Build Coastguard Worker // specified parameter does not exist, returns an empty string. Calling this
61*635a8641SAndroid Build Coastguard Worker // function will result in the associated field trial being marked as active if
62*635a8641SAndroid Build Coastguard Worker // found (i.e. group() will be called on it), if it wasn't already. Thread safe.
63*635a8641SAndroid Build Coastguard Worker BASE_EXPORT std::string GetFieldTrialParamValueByFeature(
64*635a8641SAndroid Build Coastguard Worker     const base::Feature& feature,
65*635a8641SAndroid Build Coastguard Worker     const std::string& param_name);
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
68*635a8641SAndroid Build Coastguard Worker // string value into an int using base::StringToInt() and returns it, if
69*635a8641SAndroid Build Coastguard Worker // successful. Otherwise, it returns |default_value|. If the string value is not
70*635a8641SAndroid Build Coastguard Worker // empty and the conversion does not succeed, it produces a warning to LOG.
71*635a8641SAndroid Build Coastguard Worker BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature,
72*635a8641SAndroid Build Coastguard Worker                                                  const std::string& param_name,
73*635a8641SAndroid Build Coastguard Worker                                                  int default_value);
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
76*635a8641SAndroid Build Coastguard Worker // string value into a double using base::StringToDouble() and returns it, if
77*635a8641SAndroid Build Coastguard Worker // successful. Otherwise, it returns |default_value|. If the string value is not
78*635a8641SAndroid Build Coastguard Worker // empty and the conversion does not succeed, it produces a warning to LOG.
79*635a8641SAndroid Build Coastguard Worker BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble(
80*635a8641SAndroid Build Coastguard Worker     const base::Feature& feature,
81*635a8641SAndroid Build Coastguard Worker     const std::string& param_name,
82*635a8641SAndroid Build Coastguard Worker     double default_value);
83*635a8641SAndroid Build Coastguard Worker 
84*635a8641SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
85*635a8641SAndroid Build Coastguard Worker // string value into a boolean and returns it, if successful. Otherwise, it
86*635a8641SAndroid Build Coastguard Worker // returns |default_value|. The only string representations accepted here are
87*635a8641SAndroid Build Coastguard Worker // "true" and "false". If the string value is not empty and the conversion does
88*635a8641SAndroid Build Coastguard Worker // not succeed, it produces a warning to LOG.
89*635a8641SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool(
90*635a8641SAndroid Build Coastguard Worker     const base::Feature& feature,
91*635a8641SAndroid Build Coastguard Worker     const std::string& param_name,
92*635a8641SAndroid Build Coastguard Worker     bool default_value);
93*635a8641SAndroid Build Coastguard Worker 
94*635a8641SAndroid Build Coastguard Worker // Shared declaration for various FeatureParam<T> types.
95*635a8641SAndroid Build Coastguard Worker //
96*635a8641SAndroid Build Coastguard Worker // This template is defined for the following types T:
97*635a8641SAndroid Build Coastguard Worker //   bool
98*635a8641SAndroid Build Coastguard Worker //   int
99*635a8641SAndroid Build Coastguard Worker //   double
100*635a8641SAndroid Build Coastguard Worker //   std::string
101*635a8641SAndroid Build Coastguard Worker //   enum types
102*635a8641SAndroid Build Coastguard Worker //
103*635a8641SAndroid Build Coastguard Worker // See the individual definitions below for the appropriate interfaces.
104*635a8641SAndroid Build Coastguard Worker // Attempting to use it with any other type is a compile error.
105*635a8641SAndroid Build Coastguard Worker template <typename T, bool IsEnum = std::is_enum<T>::value>
106*635a8641SAndroid Build Coastguard Worker struct FeatureParam {
107*635a8641SAndroid Build Coastguard Worker   // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
108*635a8641SAndroid Build Coastguard Worker   // in its definition so that evaluation is deferred until the template is
109*635a8641SAndroid Build Coastguard Worker   // instantiated.
110*635a8641SAndroid Build Coastguard Worker   static_assert(!std::is_same<T, T>::value, "unsupported FeatureParam<> type");
111*635a8641SAndroid Build Coastguard Worker };
112*635a8641SAndroid Build Coastguard Worker 
113*635a8641SAndroid Build Coastguard Worker // Declares a string-valued parameter. Example:
114*635a8641SAndroid Build Coastguard Worker //
115*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<string> kAssistantName{
116*635a8641SAndroid Build Coastguard Worker //         &kAssistantFeature, "assistant_name", "HAL"};
117*635a8641SAndroid Build Coastguard Worker //
118*635a8641SAndroid Build Coastguard Worker // If the feature is not set, or set to the empty string, then Get() will return
119*635a8641SAndroid Build Coastguard Worker // the default value.
120*635a8641SAndroid Build Coastguard Worker template <>
121*635a8641SAndroid Build Coastguard Worker struct FeatureParam<std::string> {
122*635a8641SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
123*635a8641SAndroid Build Coastguard Worker                          const char* name,
124*635a8641SAndroid Build Coastguard Worker                          const char* default_value)
125*635a8641SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker   BASE_EXPORT std::string Get() const;
128*635a8641SAndroid Build Coastguard Worker 
129*635a8641SAndroid Build Coastguard Worker   const Feature* const feature;
130*635a8641SAndroid Build Coastguard Worker   const char* const name;
131*635a8641SAndroid Build Coastguard Worker   const char* const default_value;
132*635a8641SAndroid Build Coastguard Worker };
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker // Declares a double-valued parameter. Example:
135*635a8641SAndroid Build Coastguard Worker //
136*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<double> kAssistantTriggerThreshold{
137*635a8641SAndroid Build Coastguard Worker //         &kAssistantFeature, "trigger_threshold", 0.10};
138*635a8641SAndroid Build Coastguard Worker //
139*635a8641SAndroid Build Coastguard Worker // If the feature is not set, or set to an invalid double value, then Get() will
140*635a8641SAndroid Build Coastguard Worker // return the default value.
141*635a8641SAndroid Build Coastguard Worker template <>
142*635a8641SAndroid Build Coastguard Worker struct FeatureParam<double> {
143*635a8641SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
144*635a8641SAndroid Build Coastguard Worker                          const char* name,
145*635a8641SAndroid Build Coastguard Worker                          double default_value)
146*635a8641SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
147*635a8641SAndroid Build Coastguard Worker 
148*635a8641SAndroid Build Coastguard Worker   BASE_EXPORT double Get() const;
149*635a8641SAndroid Build Coastguard Worker 
150*635a8641SAndroid Build Coastguard Worker   const Feature* const feature;
151*635a8641SAndroid Build Coastguard Worker   const char* const name;
152*635a8641SAndroid Build Coastguard Worker   const double default_value;
153*635a8641SAndroid Build Coastguard Worker };
154*635a8641SAndroid Build Coastguard Worker 
155*635a8641SAndroid Build Coastguard Worker // Declares an int-valued parameter. Example:
156*635a8641SAndroid Build Coastguard Worker //
157*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<int> kAssistantParallelism{
158*635a8641SAndroid Build Coastguard Worker //         &kAssistantFeature, "parallelism", 4};
159*635a8641SAndroid Build Coastguard Worker //
160*635a8641SAndroid Build Coastguard Worker // If the feature is not set, or set to an invalid int value, then Get() will
161*635a8641SAndroid Build Coastguard Worker // return the default value.
162*635a8641SAndroid Build Coastguard Worker template <>
163*635a8641SAndroid Build Coastguard Worker struct FeatureParam<int> {
164*635a8641SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
165*635a8641SAndroid Build Coastguard Worker                          const char* name,
166*635a8641SAndroid Build Coastguard Worker                          int default_value)
167*635a8641SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
168*635a8641SAndroid Build Coastguard Worker 
169*635a8641SAndroid Build Coastguard Worker   BASE_EXPORT int Get() const;
170*635a8641SAndroid Build Coastguard Worker 
171*635a8641SAndroid Build Coastguard Worker   const Feature* const feature;
172*635a8641SAndroid Build Coastguard Worker   const char* const name;
173*635a8641SAndroid Build Coastguard Worker   const int default_value;
174*635a8641SAndroid Build Coastguard Worker };
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker // Declares a bool-valued parameter. Example:
177*635a8641SAndroid Build Coastguard Worker //
178*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<int> kAssistantIsHelpful{
179*635a8641SAndroid Build Coastguard Worker //         &kAssistantFeature, "is_helpful", true};
180*635a8641SAndroid Build Coastguard Worker //
181*635a8641SAndroid Build Coastguard Worker // If the feature is not set, or set to value other than "true" or "false", then
182*635a8641SAndroid Build Coastguard Worker // Get() will return the default value.
183*635a8641SAndroid Build Coastguard Worker template <>
184*635a8641SAndroid Build Coastguard Worker struct FeatureParam<bool> {
185*635a8641SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
186*635a8641SAndroid Build Coastguard Worker                          const char* name,
187*635a8641SAndroid Build Coastguard Worker                          bool default_value)
188*635a8641SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
189*635a8641SAndroid Build Coastguard Worker 
190*635a8641SAndroid Build Coastguard Worker   BASE_EXPORT bool Get() const;
191*635a8641SAndroid Build Coastguard Worker 
192*635a8641SAndroid Build Coastguard Worker   const Feature* const feature;
193*635a8641SAndroid Build Coastguard Worker   const char* const name;
194*635a8641SAndroid Build Coastguard Worker   const bool default_value;
195*635a8641SAndroid Build Coastguard Worker };
196*635a8641SAndroid Build Coastguard Worker 
197*635a8641SAndroid Build Coastguard Worker BASE_EXPORT void LogInvalidEnumValue(const Feature& feature,
198*635a8641SAndroid Build Coastguard Worker                                      const std::string& param_name,
199*635a8641SAndroid Build Coastguard Worker                                      const std::string& value_as_string,
200*635a8641SAndroid Build Coastguard Worker                                      int default_value_as_int);
201*635a8641SAndroid Build Coastguard Worker 
202*635a8641SAndroid Build Coastguard Worker // Feature param declaration for an enum, with associated options. Example:
203*635a8641SAndroid Build Coastguard Worker //
204*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<ShapeEnum>::Option[] kShapeParamOptions[] = {
205*635a8641SAndroid Build Coastguard Worker //         {SHAPE_CIRCLE, "circle"},
206*635a8641SAndroid Build Coastguard Worker //         {SHAPE_CYLINDER, "cylinder"},
207*635a8641SAndroid Build Coastguard Worker //         {SHAPE_PAPERCLIP, "paperclip"}};
208*635a8641SAndroid Build Coastguard Worker //     constexpr FeatureParam<ShapeEnum> kAssistantShapeParam{
209*635a8641SAndroid Build Coastguard Worker //         &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions};
210*635a8641SAndroid Build Coastguard Worker //
211*635a8641SAndroid Build Coastguard Worker // With this declaration, the parameter may be set to "circle", "cylinder", or
212*635a8641SAndroid Build Coastguard Worker // "paperclip", and that will be translated to one of the three enum values. By
213*635a8641SAndroid Build Coastguard Worker // default, or if the param is set to an unknown value, the parameter will be
214*635a8641SAndroid Build Coastguard Worker // assumed to be SHAPE_CIRCLE.
215*635a8641SAndroid Build Coastguard Worker template <typename Enum>
216*635a8641SAndroid Build Coastguard Worker struct FeatureParam<Enum, true> {
217*635a8641SAndroid Build Coastguard Worker   struct Option {
218*635a8641SAndroid Build Coastguard Worker     constexpr Option(Enum value, const char* name) : value(value), name(name) {}
219*635a8641SAndroid Build Coastguard Worker 
220*635a8641SAndroid Build Coastguard Worker     const Enum value;
221*635a8641SAndroid Build Coastguard Worker     const char* const name;
222*635a8641SAndroid Build Coastguard Worker   };
223*635a8641SAndroid Build Coastguard Worker 
224*635a8641SAndroid Build Coastguard Worker   template <size_t option_count>
225*635a8641SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
226*635a8641SAndroid Build Coastguard Worker                          const char* name,
227*635a8641SAndroid Build Coastguard Worker                          const Enum default_value,
228*635a8641SAndroid Build Coastguard Worker                          const Option (*options)[option_count])
229*635a8641SAndroid Build Coastguard Worker       : feature(feature),
230*635a8641SAndroid Build Coastguard Worker         name(name),
231*635a8641SAndroid Build Coastguard Worker         default_value(default_value),
232*635a8641SAndroid Build Coastguard Worker         options(*options),
233*635a8641SAndroid Build Coastguard Worker         option_count(option_count) {
234*635a8641SAndroid Build Coastguard Worker     static_assert(option_count >= 1, "FeatureParam<enum> has no options");
235*635a8641SAndroid Build Coastguard Worker   }
236*635a8641SAndroid Build Coastguard Worker 
237*635a8641SAndroid Build Coastguard Worker   Enum Get() const {
238*635a8641SAndroid Build Coastguard Worker     std::string value = GetFieldTrialParamValueByFeature(*feature, name);
239*635a8641SAndroid Build Coastguard Worker     if (value.empty())
240*635a8641SAndroid Build Coastguard Worker       return default_value;
241*635a8641SAndroid Build Coastguard Worker     for (size_t i = 0; i < option_count; ++i) {
242*635a8641SAndroid Build Coastguard Worker       if (value == options[i].name)
243*635a8641SAndroid Build Coastguard Worker         return options[i].value;
244*635a8641SAndroid Build Coastguard Worker     }
245*635a8641SAndroid Build Coastguard Worker     LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value));
246*635a8641SAndroid Build Coastguard Worker     return default_value;
247*635a8641SAndroid Build Coastguard Worker   }
248*635a8641SAndroid Build Coastguard Worker 
249*635a8641SAndroid Build Coastguard Worker   const base::Feature* const feature;
250*635a8641SAndroid Build Coastguard Worker   const char* const name;
251*635a8641SAndroid Build Coastguard Worker   const Enum default_value;
252*635a8641SAndroid Build Coastguard Worker   const Option* const options;
253*635a8641SAndroid Build Coastguard Worker   const size_t option_count;
254*635a8641SAndroid Build Coastguard Worker };
255*635a8641SAndroid Build Coastguard Worker 
256*635a8641SAndroid Build Coastguard Worker }  // namespace base
257*635a8641SAndroid Build Coastguard Worker 
258*635a8641SAndroid Build Coastguard Worker #endif  // BASE_METRICS_FIELD_TRIAL_PARAMS_H_
259