1 // Copyright 2015 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 "chrome/browser/android/metrics/uma_session_stats.h"
7 #include "base/android/jni_string.h"
8 #include "base/command_line.h"
9 #include "base/metrics/histogram.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
15 #include "chrome/browser/metrics/metrics_services_manager.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/installer/util/google_update_settings.h"
19 #include "components/metrics/metrics_service.h"
20 #include "components/variations/metrics_util.h"
21 #include "components/variations/variations_associated_data.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/user_metrics.h"
24 #include "jni/UmaSessionStats_jni.h"
26 using base::android::ConvertJavaStringToUTF8
;
27 using base::UserMetricsAction
;
30 UmaSessionStats
* g_uma_session_stats
= NULL
;
33 UmaSessionStats::UmaSessionStats()
34 : active_session_count_(0) {
37 UmaSessionStats::~UmaSessionStats() {
40 void UmaSessionStats::UmaResumeSession(JNIEnv
* env
, jobject obj
) {
41 DCHECK(g_browser_process
);
43 if (active_session_count_
== 0) {
44 session_start_time_
= base::TimeTicks::Now();
46 // Tell the metrics service that the application resumes.
47 metrics::MetricsService
* metrics
= g_browser_process
->metrics_service();
49 metrics
->OnAppEnterForeground();
52 ++active_session_count_
;
55 void UmaSessionStats::UmaEndSession(JNIEnv
* env
, jobject obj
) {
56 --active_session_count_
;
57 DCHECK_GE(active_session_count_
, 0);
59 if (active_session_count_
== 0) {
60 base::TimeDelta duration
= base::TimeTicks::Now() - session_start_time_
;
61 UMA_HISTOGRAM_LONG_TIMES("Session.TotalDuration", duration
);
63 DCHECK(g_browser_process
);
64 // Tell the metrics service it was cleanly shutdown.
65 metrics::MetricsService
* metrics
= g_browser_process
->metrics_service();
67 metrics
->OnAppEnterBackground();
73 void UmaSessionStats::RegisterSyntheticFieldTrialWithNameHash(
74 uint32_t trial_name_hash
,
75 const std::string
& group_name
) {
76 ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameHash(
77 trial_name_hash
, group_name
);
81 void UmaSessionStats::RegisterSyntheticFieldTrial(
82 const std::string
& trial_name
,
83 const std::string
& group_name
) {
84 ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(trial_name
,
88 // Starts/stops the MetricsService when permissions have changed.
89 // There are three possible states:
90 // * Logs are being recorded and being uploaded to the server.
91 // * Logs are being recorded, but not being uploaded to the server.
92 // This happens when we've got permission to upload on Wi-Fi but we're on a
93 // mobile connection (for example).
94 // * Logs are neither being recorded or uploaded.
95 static void UpdateMetricsServiceState(JNIEnv
* env
,
96 const JavaParamRef
<jobject
>& obj
,
98 jboolean may_upload
) {
99 metrics::MetricsService
* metrics
= g_browser_process
->metrics_service();
102 if (metrics
->recording_active() != may_record
) {
103 // This function puts a consent file with the ClientID in the
104 // data directory. The ID is passed to the renderer for crash
105 // reporting when things go wrong.
106 content::BrowserThread::GetBlockingPool()->PostTask(FROM_HERE
,
108 base::IgnoreResult(GoogleUpdateSettings::SetCollectStatsConsent
),
112 g_browser_process
->GetMetricsServicesManager()->UpdatePermissions(
113 may_record
, may_upload
);
116 // Renderer process crashed in the foreground.
117 static void LogRendererCrash(JNIEnv
* env
,
118 const JavaParamRef
<jclass
>& clazz
,
119 jboolean is_paused
) {
120 DCHECK(g_browser_process
);
123 // Increment the renderer crash count in stability metrics.
124 PrefService
* pref
= g_browser_process
->local_state();
126 int value
= pref
->GetInteger(prefs::kStabilityRendererCrashCount
);
127 pref
->SetInteger(prefs::kStabilityRendererCrashCount
, value
+ 1);
130 // Note: When we are paused, any UI metric we increment may not make it to
131 // the disk before we are killed. Treat the count below as a lower bound.
132 content::RecordAction(base::UserMetricsAction("MobileRendererCrashed"));
135 static void RegisterExternalExperiment(JNIEnv
* env
,
136 const JavaParamRef
<jclass
>& clazz
,
138 jint experiment_id
) {
139 const std::string group_name_utf8
= base::IntToString(experiment_id
);
141 variations::ActiveGroupId active_group
;
142 active_group
.name
= static_cast<uint32
>(study_id
);
143 active_group
.group
= metrics::HashName(group_name_utf8
);
144 variations::AssociateGoogleVariationIDForceHashes(
145 variations::GOOGLE_WEB_PROPERTIES
, active_group
,
146 static_cast<variations::VariationID
>(experiment_id
));
148 UmaSessionStats::RegisterSyntheticFieldTrialWithNameHash(
149 static_cast<uint32_t>(study_id
), group_name_utf8
);
152 static void RegisterSyntheticFieldTrial(
154 const JavaParamRef
<jclass
>& clazz
,
155 const JavaParamRef
<jstring
>& jtrial_name
,
156 const JavaParamRef
<jstring
>& jgroup_name
) {
157 std::string
trial_name(ConvertJavaStringToUTF8(env
, jtrial_name
));
158 std::string
group_name(ConvertJavaStringToUTF8(env
, jgroup_name
));
159 UmaSessionStats::RegisterSyntheticFieldTrial(trial_name
, group_name
);
162 static void RecordMultiWindowSession(JNIEnv
*,
163 const JavaParamRef
<jclass
>&,
165 jint instance_count
) {
166 UMA_HISTOGRAM_PERCENTAGE("MobileStartup.MobileMultiWindowSession",
168 // Make sure the bucket count is the same as the range. This currently
169 // expects no more than 10 simultaneous multi window instances.
170 UMA_HISTOGRAM_CUSTOM_COUNTS("MobileStartup.MobileMultiWindowInstances",
174 10 /* bucket count */);
177 static void RecordTabCountPerLoad(JNIEnv
*,
178 const JavaParamRef
<jclass
>&,
180 // Record how many tabs total are open.
181 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", num_tabs
, 1, 200, 50);
184 static void RecordPageLoaded(JNIEnv
*,
185 const JavaParamRef
<jclass
>&,
186 jboolean is_desktop_user_agent
) {
187 // Should be called whenever a page has been loaded.
188 content::RecordAction(UserMetricsAction("MobilePageLoaded"));
189 if (is_desktop_user_agent
) {
190 content::RecordAction(
191 UserMetricsAction("MobilePageLoadedDesktopUserAgent"));
195 static void RecordPageLoadedWithKeyboard(JNIEnv
*, const JavaParamRef
<jclass
>&) {
196 content::RecordAction(UserMetricsAction("MobilePageLoadedWithKeyboard"));
199 static jlong
Init(JNIEnv
* env
, const JavaParamRef
<jclass
>& obj
) {
200 // We should have only one UmaSessionStats instance.
201 DCHECK(!g_uma_session_stats
);
202 g_uma_session_stats
= new UmaSessionStats();
203 return reinterpret_cast<intptr_t>(g_uma_session_stats
);
206 // Register native methods
207 bool RegisterUmaSessionStats(JNIEnv
* env
) {
208 return RegisterNativesImpl(env
);