xref: /aosp_15_r20/external/cronet/base/android/field_trial_list.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 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 #include <jni.h>
6 
7 #include <map>
8 #include <string>
9 
10 #include "base/base_jni/FieldTrialList_jni.h"
11 #include "base/lazy_instance.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/field_trial_list_including_low_anonymity.h"
14 #include "base/metrics/field_trial_params.h"
15 
16 namespace {
17 
18 // Log trials and their groups on activation, for debugging purposes.
19 class TrialLogger : public base::FieldTrialList::Observer {
20  public:
TrialLogger()21   TrialLogger() {}
22 
23   TrialLogger(const TrialLogger&) = delete;
24   TrialLogger& operator=(const TrialLogger&) = delete;
25 
OnFieldTrialGroupFinalized(const base::FieldTrial & trial,const std::string & group_name)26   void OnFieldTrialGroupFinalized(const base::FieldTrial& trial,
27                                   const std::string& group_name) override {
28     Log(trial.trial_name(), group_name);
29   }
30 
Log(const std::string & trial_name,const std::string & group_name)31   static void Log(const std::string& trial_name,
32                   const std::string& group_name) {
33     // Changes to format of the log message below must be accompanied by
34     // changes to finch smoke tests since they look for this log message
35     // in the logcat.
36     LOG(INFO) << "Active field trial \"" << trial_name
37               << "\" in group \"" << group_name<< '"';
38   }
39 
40  protected:
~TrialLogger()41   ~TrialLogger() override {}
42 };
43 
44 base::LazyInstance<TrialLogger>::Leaky g_trial_logger =
45     LAZY_INSTANCE_INITIALIZER;
46 
47 }  // namespace
48 
JNI_FieldTrialList_FindFullName(JNIEnv * env,std::string & trial_name)49 static std::string JNI_FieldTrialList_FindFullName(JNIEnv* env,
50                                                    std::string& trial_name) {
51   return base::FieldTrialList::FindFullName(trial_name);
52 }
53 
JNI_FieldTrialList_TrialExists(JNIEnv * env,std::string & trial_name)54 static jboolean JNI_FieldTrialList_TrialExists(JNIEnv* env,
55                                                std::string& trial_name) {
56   return base::FieldTrialList::TrialExists(trial_name);
57 }
58 
JNI_FieldTrialList_GetVariationParameter(JNIEnv * env,std::string & trial_name,std::string & parameter_key)59 static std::string JNI_FieldTrialList_GetVariationParameter(
60     JNIEnv* env,
61     std::string& trial_name,
62     std::string& parameter_key) {
63   std::map<std::string, std::string> parameters;
64   base::GetFieldTrialParams(trial_name, &parameters);
65   return parameters[parameter_key];
66 }
67 
68 // JNI_FieldTrialList_LogActiveTrials() is static function, this makes friending
69 // it a hassle because it must be declared in the file that the friend
70 // declaration is in, but its declaration can't be included in multiple places
71 // or things get messy and the linker gets mad. This helper class exists only to
72 // friend the JNI function and is, in turn, friended by
73 // FieldTrialListIncludingLowAnonymity which allows for the private
74 // GetActiveFieldTrialGroups() to be reached.
75 class AndroidFieldTrialListLogActiveTrialsFriendHelper {
76  private:
77   friend void ::JNI_FieldTrialList_LogActiveTrials(JNIEnv* env);
78 
AddObserver(base::FieldTrialList::Observer * observer)79   static bool AddObserver(base::FieldTrialList::Observer* observer) {
80     return base::FieldTrialListIncludingLowAnonymity::AddObserver(observer);
81   }
82 
GetActiveFieldTrialGroups(base::FieldTrial::ActiveGroups * active_groups)83   static void GetActiveFieldTrialGroups(
84       base::FieldTrial::ActiveGroups* active_groups) {
85     base::FieldTrialListIncludingLowAnonymity::GetActiveFieldTrialGroups(
86         active_groups);
87   }
88 };
89 
JNI_FieldTrialList_LogActiveTrials(JNIEnv * env)90 static void JNI_FieldTrialList_LogActiveTrials(JNIEnv* env) {
91   DCHECK(!g_trial_logger.IsCreated()); // This need only be called once.
92 
93   LOG(INFO) << "Logging active field trials...";
94   AndroidFieldTrialListLogActiveTrialsFriendHelper::AddObserver(
95       &g_trial_logger.Get());
96 
97   // Log any trials that were already active before adding the observer.
98   std::vector<base::FieldTrial::ActiveGroup> active_groups;
99   AndroidFieldTrialListLogActiveTrialsFriendHelper::GetActiveFieldTrialGroups(
100       &active_groups);
101   for (const base::FieldTrial::ActiveGroup& group : active_groups) {
102     TrialLogger::Log(group.trial_name, group.group_name);
103   }
104 }
105 
JNI_FieldTrialList_CreateFieldTrial(JNIEnv * env,std::string & trial_name,std::string & group_name)106 static jboolean JNI_FieldTrialList_CreateFieldTrial(JNIEnv* env,
107                                                     std::string& trial_name,
108                                                     std::string& group_name) {
109   return base::FieldTrialList::CreateFieldTrial(trial_name, group_name) !=
110          nullptr;
111 }
112