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"
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/statistics_recorder.h"
14 #include "base/synchronization/lock.h"
15 #include "base/time/time.h"
16 #include "jni/RecordHistogram_jni.h"
22 // Simple thread-safe wrapper for caching histograms. This avoids
23 // relatively expensive JNI string translation for each recording.
24 class HistogramCache
{
28 HistogramBase
* BooleanHistogram(JNIEnv
* env
,
29 jstring j_histogram_name
,
30 jint j_histogram_key
) {
31 DCHECK(j_histogram_name
);
32 DCHECK(j_histogram_key
);
33 HistogramBase
* histogram
= FindLocked(j_histogram_key
);
37 std::string histogram_name
= ConvertJavaStringToUTF8(env
, j_histogram_name
);
38 histogram
= BooleanHistogram::FactoryGet(
39 histogram_name
, HistogramBase::kUmaTargetedHistogramFlag
);
40 return InsertLocked(j_histogram_key
, histogram
);
43 HistogramBase
* EnumeratedHistogram(JNIEnv
* env
,
44 jstring j_histogram_name
,
47 DCHECK(j_histogram_name
);
48 DCHECK(j_histogram_key
);
49 HistogramBase
* histogram
= FindLocked(j_histogram_key
);
50 int boundary
= static_cast<int>(j_boundary
);
52 DCHECK(histogram
->HasConstructionArguments(1, boundary
, boundary
+ 1));
56 std::string histogram_name
= ConvertJavaStringToUTF8(env
, j_histogram_name
);
58 LinearHistogram::FactoryGet(histogram_name
, 1, boundary
, boundary
+ 1,
59 HistogramBase::kUmaTargetedHistogramFlag
);
60 return InsertLocked(j_histogram_key
, histogram
);
63 HistogramBase
* CustomTimesHistogram(JNIEnv
* env
,
64 jstring j_histogram_name
,
68 jint j_bucket_count
) {
69 DCHECK(j_histogram_name
);
70 DCHECK(j_histogram_key
);
71 HistogramBase
* histogram
= FindLocked(j_histogram_key
);
72 int64 min
= static_cast<int64
>(j_min
);
73 int64 max
= static_cast<int64
>(j_max
);
74 int bucket_count
= static_cast<int>(j_bucket_count
);
76 DCHECK(histogram
->HasConstructionArguments(min
, max
, bucket_count
));
80 std::string histogram_name
= ConvertJavaStringToUTF8(env
, j_histogram_name
);
81 // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
82 // is just a convenience for constructing the underlying Histogram with
83 // TimeDelta arguments.
84 histogram
= Histogram::FactoryGet(histogram_name
, min
, max
, bucket_count
,
85 HistogramBase::kUmaTargetedHistogramFlag
);
86 return InsertLocked(j_histogram_key
, histogram
);
90 HistogramBase
* FindLocked(jint j_histogram_key
) {
91 base::AutoLock
locked(lock_
);
92 auto histogram_it
= histograms_
.find(j_histogram_key
);
93 return histogram_it
!= histograms_
.end() ? histogram_it
->second
: nullptr;
96 HistogramBase
* InsertLocked(jint j_histogram_key
, HistogramBase
* histogram
) {
97 base::AutoLock
locked(lock_
);
98 histograms_
.insert(std::make_pair(j_histogram_key
, histogram
));
103 std::map
<jint
, HistogramBase
*> histograms_
;
105 DISALLOW_COPY_AND_ASSIGN(HistogramCache
);
108 base::LazyInstance
<HistogramCache
>::Leaky g_histograms
;
112 void RecordBooleanHistogram(JNIEnv
* env
,
114 jstring j_histogram_name
,
115 jint j_histogram_key
,
117 bool sample
= static_cast<bool>(j_sample
);
119 .BooleanHistogram(env
, j_histogram_name
, j_histogram_key
)
120 ->AddBoolean(sample
);
123 void RecordEnumeratedHistogram(JNIEnv
* env
,
125 jstring j_histogram_name
,
126 jint j_histogram_key
,
129 int sample
= static_cast<int>(j_sample
);
132 .EnumeratedHistogram(env
, j_histogram_name
, j_histogram_key
, j_boundary
)
136 void RecordCustomTimesHistogramMilliseconds(JNIEnv
* env
,
138 jstring j_histogram_name
,
139 jint j_histogram_key
,
143 jint j_num_buckets
) {
145 .CustomTimesHistogram(env
, j_histogram_name
, j_histogram_key
, j_min
,
146 j_max
, j_num_buckets
)
147 ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64
>(j_duration
)));
150 void Initialize(JNIEnv
* env
, jclass
) {
151 StatisticsRecorder::Initialize();
154 // This backs a Java test util for testing histograms -
155 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
156 // currently can't have test-specific native code packaged in test-specific Java
157 // targets - see http://crbug.com/415945.
158 jint
GetHistogramValueCountForTesting(JNIEnv
* env
,
160 jstring histogram_name
,
162 HistogramBase
* histogram
= StatisticsRecorder::FindHistogram(
163 android::ConvertJavaStringToUTF8(env
, histogram_name
));
164 if (histogram
== nullptr) {
165 // No samples have been recorded for this histogram (yet?).
169 scoped_ptr
<HistogramSamples
> samples
= histogram
->SnapshotSamples();
170 return samples
->GetCount(static_cast<int>(sample
));
173 bool RegisterRecordHistogram(JNIEnv
* env
) {
174 return RegisterNativesImpl(env
);
177 } // namespace android