Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / base / android / record_histogram.cc
blob9a68deca54f420aa2136608dc9b097b2f08fb27a
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/android/record_histogram.h"
7 #include <map>
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/lazy_instance.h"
12 #include "base/metrics/histogram.h"
13 #include "base/metrics/sparse_histogram.h"
14 #include "base/metrics/statistics_recorder.h"
15 #include "base/synchronization/lock.h"
16 #include "base/time/time.h"
17 #include "jni/RecordHistogram_jni.h"
19 namespace base {
20 namespace android {
21 namespace {
23 // Simple thread-safe wrapper for caching histograms. This avoids
24 // relatively expensive JNI string translation for each recording.
25 class HistogramCache {
26 public:
27 HistogramCache() {}
29 HistogramBase* BooleanHistogram(JNIEnv* env,
30 jstring j_histogram_name,
31 jint j_histogram_key) {
32 DCHECK(j_histogram_name);
33 DCHECK(j_histogram_key);
34 HistogramBase* histogram = FindLocked(j_histogram_key);
35 if (histogram)
36 return histogram;
38 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
39 histogram = BooleanHistogram::FactoryGet(
40 histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
41 return InsertLocked(j_histogram_key, histogram);
44 HistogramBase* EnumeratedHistogram(JNIEnv* env,
45 jstring j_histogram_name,
46 jint j_histogram_key,
47 jint j_boundary) {
48 DCHECK(j_histogram_name);
49 DCHECK(j_histogram_key);
50 HistogramBase* histogram = FindLocked(j_histogram_key);
51 int boundary = static_cast<int>(j_boundary);
52 if (histogram) {
53 DCHECK(histogram->HasConstructionArguments(1, boundary, boundary + 1));
54 return histogram;
57 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
58 histogram =
59 LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
60 HistogramBase::kUmaTargetedHistogramFlag);
61 return InsertLocked(j_histogram_key, histogram);
64 HistogramBase* CustomCountHistogram(JNIEnv* env,
65 jstring j_histogram_name,
66 jint j_histogram_key,
67 jint j_min,
68 jint j_max,
69 jint j_num_buckets) {
70 DCHECK(j_histogram_name);
71 DCHECK(j_histogram_key);
72 int64 min = static_cast<int64>(j_min);
73 int64 max = static_cast<int64>(j_max);
74 int num_buckets = static_cast<int>(j_num_buckets);
75 HistogramBase* histogram = FindLocked(j_histogram_key);
76 if (histogram) {
77 DCHECK(histogram->HasConstructionArguments(min, max, num_buckets));
78 return histogram;
81 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
82 histogram =
83 Histogram::FactoryGet(histogram_name, min, max, num_buckets,
84 HistogramBase::kUmaTargetedHistogramFlag);
85 return InsertLocked(j_histogram_key, histogram);
88 HistogramBase* SparseHistogram(JNIEnv* env,
89 jstring j_histogram_name,
90 jint j_histogram_key) {
91 DCHECK(j_histogram_name);
92 DCHECK(j_histogram_key);
93 HistogramBase* histogram = FindLocked(j_histogram_key);
94 if (histogram)
95 return histogram;
97 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
98 histogram = SparseHistogram::FactoryGet(
99 histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
100 return InsertLocked(j_histogram_key, histogram);
103 HistogramBase* CustomTimesHistogram(JNIEnv* env,
104 jstring j_histogram_name,
105 jint j_histogram_key,
106 jlong j_min,
107 jlong j_max,
108 jint j_bucket_count) {
109 DCHECK(j_histogram_name);
110 DCHECK(j_histogram_key);
111 HistogramBase* histogram = FindLocked(j_histogram_key);
112 int64 min = static_cast<int64>(j_min);
113 int64 max = static_cast<int64>(j_max);
114 int bucket_count = static_cast<int>(j_bucket_count);
115 if (histogram) {
116 DCHECK(histogram->HasConstructionArguments(min, max, bucket_count));
117 return histogram;
120 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
121 // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
122 // is just a convenience for constructing the underlying Histogram with
123 // TimeDelta arguments.
124 histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
125 HistogramBase::kUmaTargetedHistogramFlag);
126 return InsertLocked(j_histogram_key, histogram);
129 private:
130 HistogramBase* FindLocked(jint j_histogram_key) {
131 base::AutoLock locked(lock_);
132 auto histogram_it = histograms_.find(j_histogram_key);
133 return histogram_it != histograms_.end() ? histogram_it->second : nullptr;
136 HistogramBase* InsertLocked(jint j_histogram_key, HistogramBase* histogram) {
137 base::AutoLock locked(lock_);
138 histograms_.insert(std::make_pair(j_histogram_key, histogram));
139 return histogram;
142 base::Lock lock_;
143 std::map<jint, HistogramBase*> histograms_;
145 DISALLOW_COPY_AND_ASSIGN(HistogramCache);
148 base::LazyInstance<HistogramCache>::Leaky g_histograms;
150 } // namespace
152 void RecordBooleanHistogram(JNIEnv* env,
153 jclass clazz,
154 jstring j_histogram_name,
155 jint j_histogram_key,
156 jboolean j_sample) {
157 bool sample = static_cast<bool>(j_sample);
158 g_histograms.Get()
159 .BooleanHistogram(env, j_histogram_name, j_histogram_key)
160 ->AddBoolean(sample);
163 void RecordEnumeratedHistogram(JNIEnv* env,
164 jclass clazz,
165 jstring j_histogram_name,
166 jint j_histogram_key,
167 jint j_sample,
168 jint j_boundary) {
169 int sample = static_cast<int>(j_sample);
171 g_histograms.Get()
172 .EnumeratedHistogram(env, j_histogram_name, j_histogram_key, j_boundary)
173 ->Add(sample);
176 void RecordCustomCountHistogram(JNIEnv* env,
177 jclass clazz,
178 jstring j_histogram_name,
179 jint j_histogram_key,
180 jint j_sample,
181 jint j_min,
182 jint j_max,
183 jint j_num_buckets) {
184 int sample = static_cast<int>(j_sample);
186 g_histograms.Get()
187 .CustomCountHistogram(env, j_histogram_name, j_histogram_key, j_min,
188 j_max, j_num_buckets)
189 ->Add(sample);
192 void RecordSparseHistogram(JNIEnv* env,
193 jclass clazz,
194 jstring j_histogram_name,
195 jint j_histogram_key,
196 jint j_sample) {
197 int sample = static_cast<int>(j_sample);
198 g_histograms.Get()
199 .SparseHistogram(env, j_histogram_name, j_histogram_key)
200 ->Add(sample);
203 void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
204 jclass clazz,
205 jstring j_histogram_name,
206 jint j_histogram_key,
207 jlong j_duration,
208 jlong j_min,
209 jlong j_max,
210 jint j_num_buckets) {
211 g_histograms.Get()
212 .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min,
213 j_max, j_num_buckets)
214 ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64>(j_duration)));
217 void Initialize(JNIEnv* env, jclass) {
218 StatisticsRecorder::Initialize();
221 // This backs a Java test util for testing histograms -
222 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
223 // currently can't have test-specific native code packaged in test-specific Java
224 // targets - see http://crbug.com/415945.
225 jint GetHistogramValueCountForTesting(JNIEnv* env,
226 jclass clazz,
227 jstring histogram_name,
228 jint sample) {
229 HistogramBase* histogram = StatisticsRecorder::FindHistogram(
230 android::ConvertJavaStringToUTF8(env, histogram_name));
231 if (histogram == nullptr) {
232 // No samples have been recorded for this histogram (yet?).
233 return 0;
236 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
237 return samples->GetCount(static_cast<int>(sample));
240 bool RegisterRecordHistogram(JNIEnv* env) {
241 return RegisterNativesImpl(env);
244 } // namespace android
245 } // namespace base