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