android_metrics_provider.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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.
4
5#include "chrome/browser/metrics/android_metrics_provider.h"
6
7#include "base/metrics/histogram.h"
8#include "base/prefs/pref_registry_simple.h"
9#include "base/prefs/pref_service.h"
10#include "base/prefs/scoped_user_pref_update.h"
11#include "base/values.h"
12#include "chrome/common/pref_names.h"
13
14namespace {
15
16// Increments a particular entry in the ListValue.
17void IncrementListValue(base::ListValue* counts, int index) {
18  int current_count = 0;
19  counts->GetInteger(index, &current_count);
20  counts->Set(index, new base::FundamentalValue(current_count + 1));
21}
22
23// Takes an int corresponding to a Type and returns the corresponding flag.
24int GetActivityFlag(int type_id) {
25  ActivityTypeIds::Type type = ActivityTypeIds::GetActivityType(type_id);
26  DCHECK_LT(type, ActivityTypeIds::ACTIVITY_MAX_VALUE);
27  return (1 << type);
28}
29
30}  // namespace
31
32AndroidMetricsProvider::AndroidMetricsProvider(PrefService* local_state)
33    : local_state_(local_state) {
34  LogStabilityToPrefs();
35}
36
37AndroidMetricsProvider::~AndroidMetricsProvider() {
38}
39
40
41void AndroidMetricsProvider::ProvideStabilityMetrics(
42    metrics::SystemProfileProto* system_profile_proto) {
43  ConvertStabilityPrefsToHistograms();
44}
45
46void AndroidMetricsProvider::LogStabilityToPrefs() {
47  // Track which Activities were launched by the user.
48  // A 'launch' is defined as starting the Activity at least once during a
49  // UMA session.  Multiple launches are counted only once since it is possible
50  // for users to hop between Activities (e.g. entering and leaving Settings).
51  const int launched =
52      local_state_->GetInteger(prefs::kStabilityLaunchedActivityFlags);
53  ListPrefUpdate update_launches(local_state_,
54                                 prefs::kStabilityLaunchedActivityCounts);
55  base::ListValue* launch_counts = update_launches.Get();
56  for (int activity_type = ActivityTypeIds::ACTIVITY_NONE;
57       activity_type < ActivityTypeIds::ACTIVITY_MAX_VALUE;
58       ++activity_type) {
59    if (launched & GetActivityFlag(activity_type))
60      IncrementListValue(launch_counts, activity_type);
61  }
62  local_state_->SetInteger(prefs::kStabilityLaunchedActivityFlags, 0);
63
64  // Track any Activities that were in the foreground when Chrome died.
65  // These Activities failed to be recorded as leaving the foreground, so Chrome
66  // couldn't have ended the UMA session cleanly.  Record them as crashing.
67  const int foreground =
68      local_state_->GetInteger(prefs::kStabilityForegroundActivityType);
69  if (foreground != ActivityTypeIds::ACTIVITY_NONE) {
70    ListPrefUpdate update_crashes(local_state_,
71                                  prefs::kStabilityCrashedActivityCounts);
72    base::ListValue* crash_counts = update_crashes.Get();
73    IncrementListValue(crash_counts, foreground);
74    local_state_->SetInteger(prefs::kStabilityForegroundActivityType,
75                             ActivityTypeIds::ACTIVITY_NONE);
76  }
77
78  local_state_->CommitPendingWrite();
79}
80
81void AndroidMetricsProvider::ConvertStabilityPrefsToHistograms() {
82  ListPrefUpdate launch_updater(local_state_,
83                                prefs::kStabilityLaunchedActivityCounts);
84  ListPrefUpdate crash_updater(local_state_,
85                               prefs::kStabilityCrashedActivityCounts);
86
87  base::ListValue* launch_counts = launch_updater.Get();
88  base::ListValue* crash_counts = crash_updater.Get();
89
90  for (int activity_type = ActivityTypeIds::ACTIVITY_NONE;
91       activity_type < ActivityTypeIds::ACTIVITY_MAX_VALUE;
92       ++activity_type) {
93    int launch_count = 0;
94    int crash_count = 0;
95
96    launch_counts->GetInteger(activity_type, &launch_count);
97    crash_counts->GetInteger(activity_type, &crash_count);
98
99    for (int count = 0; count < launch_count; ++count) {
100      UMA_STABILITY_HISTOGRAM_ENUMERATION(
101          "Chrome.Android.Activity.LaunchCounts",
102          activity_type,
103          ActivityTypeIds::ACTIVITY_MAX_VALUE);
104    }
105
106    for (int count = 0; count < crash_count; ++count) {
107      UMA_STABILITY_HISTOGRAM_ENUMERATION("Chrome.Android.Activity.CrashCounts",
108                                          activity_type,
109                                          ActivityTypeIds::ACTIVITY_MAX_VALUE);
110    }
111  }
112
113  launch_counts->Clear();
114  crash_counts->Clear();
115}
116
117void AndroidMetricsProvider::OnForegroundActivityChanged(
118    ActivityTypeIds::Type type) {
119  DCHECK_LT(type, ActivityTypeIds::ACTIVITY_MAX_VALUE);
120
121  if (type == local_state_->GetInteger(prefs::kStabilityForegroundActivityType))
122    return;
123
124  // Record that the Activity is now in the foreground.
125  local_state_->SetInteger(prefs::kStabilityForegroundActivityType, type);
126
127  // Record that the Activity was launched this sesaion.
128  // The pref stores a set of flags ORed together, where each set flag
129  // corresponds to a launched Activity type.
130  int launched =
131      local_state_->GetInteger(prefs::kStabilityLaunchedActivityFlags);
132  if (type != ActivityTypeIds::ACTIVITY_NONE) {
133    launched |= GetActivityFlag(type);
134    local_state_->SetInteger(prefs::kStabilityLaunchedActivityFlags, launched);
135  }
136
137  local_state_->CommitPendingWrite();
138}
139
140// static
141void AndroidMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
142  registry->RegisterIntegerPref(prefs::kStabilityForegroundActivityType,
143                                ActivityTypeIds::ACTIVITY_NONE);
144  registry->RegisterIntegerPref(prefs::kStabilityLaunchedActivityFlags, 0);
145  registry->RegisterListPref(prefs::kStabilityLaunchedActivityCounts);
146  registry->RegisterListPref(prefs::kStabilityCrashedActivityCounts);
147}
148