diff options
22 files changed, 486 insertions, 21 deletions
diff --git a/base/base.gyp b/base/base.gyp index 4269485..78e6ddb 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -554,6 +554,7 @@ 'metrics/field_trial_unittest.cc', 'metrics/histogram_base_unittest.cc', 'metrics/histogram_delta_serialization_unittest.cc', + 'metrics/histogram_snapshot_manager_unittest.cc', 'metrics/histogram_unittest.cc', 'metrics/sparse_histogram_unittest.cc', 'metrics/stats_table_unittest.cc', diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index 9845362..7a6c688 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h @@ -190,6 +190,12 @@ class Lock; base::Histogram::FactoryGet(name, min, max, bucket_count, \ base::HistogramBase::kNoFlags)) +// This is a helper macro used by other macros and shouldn't be used directly. +#define HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary, flag) \ + STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ + base::LinearHistogram::FactoryGet(name, 1, boundary, boundary + 1, \ + flag)) + #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) @@ -349,9 +355,15 @@ class Lock; // The samples should always be strictly less than |boundary_value|. For more // details, see the comment for the |HISTOGRAM_ENUMERATION| macro, above. #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ - STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ - base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ - boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag)) + HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary_value, \ + base::HistogramBase::kUmaTargetedHistogramFlag) + +// Similar to UMA_HISTOGRAM_ENUMERATION, but used for recording stability +// histograms. Use this if recording a histogram that should be part of the +// initial stability log. +#define UMA_STABILITY_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ + HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary_value, \ + base::HistogramBase::kUmaStabilityHistogramFlag) #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h index 11b9a45b..f3e9b46 100644 --- a/base/metrics/histogram_base.h +++ b/base/metrics/histogram_base.h @@ -56,13 +56,20 @@ class BASE_EXPORT HistogramBase { enum Flags { kNoFlags = 0, - kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. - // Indicate that the histogram was pickled to be sent across an IPC Channel. - // If we observe this flag on a histogram being aggregated into after IPC, - // then we are running in a single process mode, and the aggregation should - // not take place (as we would be aggregating back into the source - // histogram!). + // Histogram should be UMA uploaded. + kUmaTargetedHistogramFlag = 0x1, + + // Indicates that this is a stability histogram. This flag exists to specify + // which histograms should be included in the initial stability log. Please + // refer to |MetricsService::PrepareInitialStabilityLog|. + kUmaStabilityHistogramFlag = kUmaTargetedHistogramFlag | 0x2, + + // Indicates that the histogram was pickled to be sent across an IPC + // Channel. If we observe this flag on a histogram being aggregated into + // after IPC, then we are running in a single process mode, and the + // aggregation should not take place (as we would be aggregating back into + // the source histogram!). kIPCSerializationSourceFlag = 0x10, // Only for Histogram and its sub classes: fancy bucket-naming support. diff --git a/base/metrics/histogram_delta_serialization.cc b/base/metrics/histogram_delta_serialization.cc index e40a6b6..e4aad13 100644 --- a/base/metrics/histogram_delta_serialization.cc +++ b/base/metrics/histogram_delta_serialization.cc @@ -66,7 +66,7 @@ void HistogramDeltaSerialization::PrepareAndSerializeDeltas( // the histograms, so that the receiving process can distinguish them from the // local histograms. histogram_snapshot_manager_.PrepareDeltas( - Histogram::kIPCSerializationSourceFlag, false); + Histogram::kIPCSerializationSourceFlag, Histogram::kNoFlags); serialized_deltas_ = NULL; } diff --git a/base/metrics/histogram_snapshot_manager.cc b/base/metrics/histogram_snapshot_manager.cc index cb594bd..b1e26da 100644 --- a/base/metrics/histogram_snapshot_manager.cc +++ b/base/metrics/histogram_snapshot_manager.cc @@ -25,18 +25,17 @@ HistogramSnapshotManager::~HistogramSnapshotManager() { STLDeleteValues(&logged_samples_); } -void HistogramSnapshotManager::PrepareDeltas(HistogramBase::Flags flag_to_set, - bool record_only_uma) { +void HistogramSnapshotManager::PrepareDeltas( + HistogramBase::Flags flag_to_set, + HistogramBase::Flags required_flags) { StatisticsRecorder::Histograms histograms; StatisticsRecorder::GetHistograms(&histograms); for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin(); histograms.end() != it; ++it) { (*it)->SetFlags(flag_to_set); - if (record_only_uma && - 0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag)) - continue; - PrepareDelta(**it); + if (((*it)->flags() & required_flags) == required_flags) + PrepareDelta(**it); } } diff --git a/base/metrics/histogram_snapshot_manager.h b/base/metrics/histogram_snapshot_manager.h index 3c70508..5a5f2e9 100644 --- a/base/metrics/histogram_snapshot_manager.h +++ b/base/metrics/histogram_snapshot_manager.h @@ -29,9 +29,13 @@ class BASE_EXPORT HistogramSnapshotManager { virtual ~HistogramSnapshotManager(); // Snapshot all histograms, and ask |histogram_flattener_| to record the - // delta. The arguments allow selecting only a subset of histograms for - // recording, or to set a flag in each recorded histogram. - void PrepareDeltas(HistogramBase::Flags flags_to_set, bool record_only_uma); + // delta. |flags_to_set| is used to set flags for each histogram. + // |required_flags| is used to select histograms to be recorded. + // Only histograms that have all the flags specified by the argument will be + // chosen. If all histograms should be recorded, set it to + // |Histogram::kNoFlags|. + void PrepareDeltas(HistogramBase::Flags flags_to_set, + HistogramBase::Flags required_flags); private: // Snapshot this histogram, and record the delta. diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc new file mode 100644 index 0000000..e6672ea --- /dev/null +++ b/base/metrics/histogram_snapshot_manager_unittest.cc @@ -0,0 +1,106 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/metrics/histogram_snapshot_manager.h" + +#include <string> +#include <vector> + +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_delta_serialization.h" +#include "base/metrics/statistics_recorder.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +class HistogramFlattenerDeltaRecorder : public HistogramFlattener { + public: + HistogramFlattenerDeltaRecorder() {} + + virtual void RecordDelta(const HistogramBase& histogram, + const HistogramSamples& snapshot) OVERRIDE { + recorded_delta_histogram_names_.push_back(histogram.histogram_name()); + } + + virtual void InconsistencyDetected( + HistogramBase::Inconsistency problem) OVERRIDE { + ASSERT_TRUE(false); + } + + virtual void UniqueInconsistencyDetected( + HistogramBase::Inconsistency problem) OVERRIDE { + ASSERT_TRUE(false); + } + + virtual void InconsistencyDetectedInLoggedCount(int amount) OVERRIDE { + ASSERT_TRUE(false); + } + + std::vector<std::string> GetRecordedDeltaHistogramNames() { + return recorded_delta_histogram_names_; + } + + private: + std::vector<std::string> recorded_delta_histogram_names_; + + DISALLOW_COPY_AND_ASSIGN(HistogramFlattenerDeltaRecorder); +}; + +class HistogramSnapshotManagerTest : public testing::Test { + protected: + HistogramSnapshotManagerTest() + : histogram_snapshot_manager_(&histogram_flattener_delta_recorder_) {} + + virtual ~HistogramSnapshotManagerTest() {} + + StatisticsRecorder statistics_recorder_; + HistogramFlattenerDeltaRecorder histogram_flattener_delta_recorder_; + HistogramSnapshotManager histogram_snapshot_manager_; +}; + +TEST_F(HistogramSnapshotManagerTest, PrepareDeltasNoFlagsFilter) { + // kNoFlags filter should record all histograms. + UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 2); + UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2); + + histogram_snapshot_manager_.PrepareDeltas(HistogramBase::kNoFlags, + HistogramBase::kNoFlags); + + const std::vector<std::string>& histograms = + histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames(); + EXPECT_EQ(2U, histograms.size()); + EXPECT_EQ("UmaHistogram", histograms[0]); + EXPECT_EQ("UmaStabilityHistogram", histograms[1]); +} + +TEST_F(HistogramSnapshotManagerTest, PrepareDeltasUmaHistogramFlagFilter) { + // Note that kUmaStabilityHistogramFlag includes kUmaTargetedHistogramFlag. + UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 2); + UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2); + + histogram_snapshot_manager_.PrepareDeltas( + HistogramBase::kNoFlags, HistogramBase::kUmaTargetedHistogramFlag); + + const std::vector<std::string>& histograms = + histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames(); + EXPECT_EQ(2U, histograms.size()); + EXPECT_EQ("UmaHistogram", histograms[0]); + EXPECT_EQ("UmaStabilityHistogram", histograms[1]); +} + +TEST_F(HistogramSnapshotManagerTest, + PrepareDeltasUmaStabilityHistogramFlagFilter) { + UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 2); + UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2); + + histogram_snapshot_manager_.PrepareDeltas( + HistogramBase::kNoFlags, HistogramBase::kUmaStabilityHistogramFlag); + + const std::vector<std::string>& histograms = + histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames(); + EXPECT_EQ(1U, histograms.size()); + EXPECT_EQ("UmaStabilityHistogram", histograms[0]); +} + +} // namespace base diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h index 5e53f274..7a81826 100644 --- a/base/metrics/statistics_recorder.h +++ b/base/metrics/statistics_recorder.h @@ -86,6 +86,7 @@ class BASE_EXPORT StatisticsRecorder { friend struct DefaultLazyInstanceTraits<StatisticsRecorder>; friend class HistogramBaseTest; + friend class HistogramSnapshotManagerTest; friend class HistogramTest; friend class SparseHistogramTest; friend class StatisticsDeltaReaderTest; diff --git a/chrome/android/java/ActivityTypeIds.template b/chrome/android/java/ActivityTypeIds.template new file mode 100644 index 0000000..4f64e8b --- /dev/null +++ b/chrome/android/java/ActivityTypeIds.template @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser; + +public class ActivityTypeIds { +#define DEFINE_ACTIVITY_ID(id,value) public static final int ACTIVITY_##id = value; +#include "chrome/browser/android/activity_type_id_list.h" +#undef DEFINE_ACTIVITY_ID +} diff --git a/chrome/browser/android/activity_type_id_list.h b/chrome/browser/android/activity_type_id_list.h new file mode 100644 index 0000000..805e15e --- /dev/null +++ b/chrome/browser/android/activity_type_id_list.h @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Intentionally no include guards because this file is meant to be included +// inside a macro to generate enum values. + +// Define Activities we are interested in tracking. IDs are assigned +// consecutively, from NONE to MAX_VALUE. Activities that are not explicitly +// defined are all assigned the UNKNOWN value. When adding new ones, make sure +// to append them after current Activities and to update the |AndroidActivityId| +// enum in |histograms.xml|. +DEFINE_ACTIVITY_ID(NONE, 0) +DEFINE_ACTIVITY_ID(UNKNOWN, 1) +DEFINE_ACTIVITY_ID(MAIN, 2) +DEFINE_ACTIVITY_ID(PREFERENCES, 3) +DEFINE_ACTIVITY_ID(WEBAPPACTIVITY, 4) +DEFINE_ACTIVITY_ID(FULLSCREENACTIVITY, 5) +DEFINE_ACTIVITY_ID(MAX_VALUE, 6) diff --git a/chrome/browser/android/activity_type_ids.cc b/chrome/browser/android/activity_type_ids.cc new file mode 100644 index 0000000..98a1724 --- /dev/null +++ b/chrome/browser/android/activity_type_ids.cc @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/activity_type_ids.h" + +#include "base/logging.h" + +namespace ActivityTypeIds { + +Type GetActivityType(int type_id) { + if (type_id >= ACTIVITY_NONE && type_id <= ACTIVITY_MAX_VALUE) + return Type(type_id); + + NOTREACHED() << "Unhandled Activity id was passed in: " << type_id; + return ACTIVITY_MAX_VALUE; +} + +} // namespace ActivityTypeIds diff --git a/chrome/browser/android/activity_type_ids.h b/chrome/browser/android/activity_type_ids.h new file mode 100644 index 0000000..606f875 --- /dev/null +++ b/chrome/browser/android/activity_type_ids.h @@ -0,0 +1,23 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_ACTIVITY_TYPE_IDS_H_ +#define CHROME_BROWSER_ANDROID_ACTIVITY_TYPE_IDS_H_ + +// This file maps Activities on Chrome to specific flags for identification. + +namespace ActivityTypeIds { + +enum Type { +#define DEFINE_ACTIVITY_ID(id,value) ACTIVITY_##id = (value), +#include "activity_type_id_list.h" +#undef DEFINE_ACTIVITY_ID +}; // enum Type + +// Takes an int corresponding to a Type and returns the corresponding Type. +Type GetActivityType(int type_id); + +} // namespace ActivityTypeIds + +#endif // CHROME_BROWSER_ANDROID_ACTIVITY_TYPE_IDS_H_ diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index cc90ada..a3c0b83 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -482,6 +482,10 @@ void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); + +#if defined(OS_ANDROID) + RegisterPrefsAndroid(registry); +#endif // defined(OS_ANDROID) } // static @@ -510,6 +514,10 @@ void MetricsService::DiscardOldStabilityStats(PrefService* local_state) { local_state->ClearPref(prefs::kMetricsInitialLogs); local_state->ClearPref(prefs::kMetricsOngoingLogs); + +#if defined(OS_ANDROID) + DiscardOldStabilityStatsAndroid(local_state); +#endif // defined(OS_ANDROID) } MetricsService::MetricsService() @@ -946,6 +954,10 @@ void MetricsService::InitializeMetricsState(ReportingState reporting_state) { session_id_ = pref->GetInteger(prefs::kMetricsSessionID); +#if defined(OS_ANDROID) + LogAndroidStabilityToPrefs(pref); +#endif // defined(OS_ANDROID) + if (!pref->GetBoolean(prefs::kStabilityExitedCleanly)) { IncrementPrefValue(prefs::kStabilityCrashCount); // Reset flag, and wait until we call LogNeedForCleanShutdown() before @@ -1534,6 +1546,10 @@ void MetricsService::PrepareInitialStabilityLog() { log_manager_.PauseCurrentLog(); log_manager_.BeginLoggingWithLog(initial_stability_log.release(), MetricsLog::INITIAL_LOG); +#if defined(OS_ANDROID) + ConvertAndroidStabilityPrefsToHistograms(pref); + RecordCurrentStabilityHistograms(); +#endif // defined(OS_ANDROID) log_manager_.FinishCurrentLog(); log_manager_.ResumePausedLog(); @@ -1560,6 +1576,9 @@ void MetricsService::PrepareInitialMetricsLog(MetricsLog::LogType log_type) { // before writing them. log_manager_.PauseCurrentLog(); log_manager_.BeginLoggingWithLog(initial_metrics_log_.release(), log_type); +#if defined(OS_ANDROID) + ConvertAndroidStabilityPrefsToHistograms(pref); +#endif // defined(OS_ANDROID) RecordCurrentHistograms(); log_manager_.FinishCurrentLog(); log_manager_.ResumePausedLog(); diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h index dadbf59..199d6b7 100644 --- a/chrome/browser/metrics/metrics_service.h +++ b/chrome/browser/metrics/metrics_service.h @@ -30,7 +30,9 @@ #include "content/public/browser/user_metrics.h" #include "net/url_request/url_fetcher_delegate.h" -#if defined(OS_CHROMEOS) +#if defined(OS_ANDROID) +#include "chrome/browser/android/activity_type_ids.h" +#elif defined(OS_CHROMEOS) #include "chrome/browser/chromeos/external_metrics.h" #endif @@ -175,6 +177,9 @@ class MetricsService // At startup, prefs needs to be called with a list of all the pref names and // types we'll be using. static void RegisterPrefs(PrefRegistrySimple* registry); +#if defined(OS_ANDROID) + static void RegisterPrefsAndroid(PrefRegistrySimple* registry); +#endif // defined(OS_ANDROID) // Set up notifications which indicate that a user is performing work. This is // useful to allow some features to sleep, until the machine becomes active, @@ -203,6 +208,18 @@ class MetricsService // that session end was successful. void RecordCompletedSessionEnd(); +#if defined(OS_ANDROID) + // Called to log launch and crash stats to preferences. + void LogAndroidStabilityToPrefs(PrefService* pref); + + // Converts crash stats stored in the preferences into histograms. + void ConvertAndroidStabilityPrefsToHistograms(PrefService* pref); + + // Called when the Activity that the user interacts with is swapped out. + void OnForegroundActivityChanged(PrefService* pref, + ActivityTypeIds::Type type); +#endif // defined(OS_ANDROID) + #if defined(OS_ANDROID) || defined(OS_IOS) // Called when the application is going into background mode. void OnAppEnterBackground(); @@ -346,6 +363,9 @@ class MetricsService // the old version (after an autoupdate has arrived), and so we'd bias // initial results towards showing crashes :-(. static void DiscardOldStabilityStats(PrefService* local_state); +#if defined(OS_ANDROID) + static void DiscardOldStabilityStatsAndroid(PrefService* local_state); +#endif // defined(OS_ANDROID) // Turns recording on or off. // DisableRecording() also forces a persistent save of logging state (if diff --git a/chrome/browser/metrics/metrics_service_android.cc b/chrome/browser/metrics/metrics_service_android.cc new file mode 100644 index 0000000..30ee40e --- /dev/null +++ b/chrome/browser/metrics/metrics_service_android.cc @@ -0,0 +1,143 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/metrics/metrics_service.h" + +#include "base/metrics/histogram.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/scoped_user_pref_update.h" +#include "base/values.h" +#include "chrome/browser/android/activity_type_ids.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/pref_names.h" + +namespace { + +// Increments a particular entry in the ListValue. +void IncrementListValue(base::ListValue* counts, int index) { + int current_count = 0; + counts->GetInteger(index, ¤t_count); + counts->Set(index, new base::FundamentalValue(current_count + 1)); +} + +// Takes an int corresponding to a Type and returns the corresponding flag. +int GetActivityFlag(int type_id) { + ActivityTypeIds::Type type = ActivityTypeIds::GetActivityType(type_id); + DCHECK_LT(type, ActivityTypeIds::ACTIVITY_MAX_VALUE); + return (1 << type); +} + +} // namespace + +// static +void MetricsService::RegisterPrefsAndroid(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref(prefs::kStabilityForegroundActivityType, + ActivityTypeIds::ACTIVITY_NONE); + registry->RegisterIntegerPref(prefs::kStabilityLaunchedActivityFlags, 0); + registry->RegisterListPref(prefs::kStabilityLaunchedActivityCounts); + registry->RegisterListPref(prefs::kStabilityCrashedActivityCounts); +} + +void MetricsService::LogAndroidStabilityToPrefs(PrefService* pref) { + // Track which Activities were launched by the user. + // A 'launch' is defined as starting the Activity at least once during a + // UMA session. Multiple launches are counted only once since it is possible + // for users to hop between Activities (e.g. entering and leaving Settings). + int launched = pref->GetInteger(prefs::kStabilityLaunchedActivityFlags); + ListPrefUpdate update_launches(pref, prefs::kStabilityLaunchedActivityCounts); + base::ListValue* launch_counts = update_launches.Get(); + for (int activity_type = ActivityTypeIds::ACTIVITY_NONE; + activity_type < ActivityTypeIds::ACTIVITY_MAX_VALUE; + ++activity_type) { + if (launched & GetActivityFlag(activity_type)) + IncrementListValue(launch_counts, activity_type); + } + pref->SetInteger(prefs::kStabilityLaunchedActivityFlags, 0); + + // Track any Activities that were in the foreground when Chrome died. + // These Activities failed to be recorded as leaving the foreground, so Chrome + // couldn't have ended the UMA session cleanly. Record them as crashing. + int foreground = pref->GetInteger(prefs::kStabilityForegroundActivityType); + if (foreground != ActivityTypeIds::ACTIVITY_NONE) { + ListPrefUpdate update_crashes(pref, prefs::kStabilityCrashedActivityCounts); + base::ListValue* crash_counts = update_crashes.Get(); + IncrementListValue(crash_counts, foreground); + pref->SetInteger(prefs::kStabilityForegroundActivityType, + ActivityTypeIds::ACTIVITY_NONE); + } + + pref->CommitPendingWrite(); +} + +void MetricsService::ConvertAndroidStabilityPrefsToHistograms( + PrefService* pref) { + ListPrefUpdate launch_updater(pref, prefs::kStabilityLaunchedActivityCounts); + ListPrefUpdate crash_updater(pref, prefs::kStabilityCrashedActivityCounts); + + base::ListValue* launch_counts = launch_updater.Get(); + base::ListValue* crash_counts = crash_updater.Get(); + + for (int activity_type = ActivityTypeIds::ACTIVITY_NONE; + activity_type < ActivityTypeIds::ACTIVITY_MAX_VALUE; + ++activity_type) { + int launch_count = 0; + int crash_count = 0; + + launch_counts->GetInteger(activity_type, &launch_count); + crash_counts->GetInteger(activity_type, &crash_count); + + for (int count = 0; count < launch_count; ++count) { + UMA_STABILITY_HISTOGRAM_ENUMERATION( + "Chrome.Android.Activity.LaunchCounts", + activity_type, + ActivityTypeIds::ACTIVITY_MAX_VALUE); + } + + for (int count = 0; count < crash_count; ++count) { + UMA_STABILITY_HISTOGRAM_ENUMERATION("Chrome.Android.Activity.CrashCounts", + activity_type, + ActivityTypeIds::ACTIVITY_MAX_VALUE); + } + } + + launch_counts->Clear(); + crash_counts->Clear(); +} + +void MetricsService::OnForegroundActivityChanged(PrefService* pref, + ActivityTypeIds::Type type) { + DCHECK(type < ActivityTypeIds::ACTIVITY_MAX_VALUE); + + int activity_type = pref->GetInteger(prefs::kStabilityForegroundActivityType); + if (activity_type == type) + return; + + // Record that the Activity is now in the foreground. + pref->SetInteger(prefs::kStabilityForegroundActivityType, type); + + // Record that the Activity was launched this sesaion. + // The pref stores a set of flags ORed together, where each set flag + // corresponds to a launched Activity type. + int launched = pref->GetInteger(prefs::kStabilityLaunchedActivityFlags); + if (type != ActivityTypeIds::ACTIVITY_NONE) { + launched |= GetActivityFlag(type); + pref->SetInteger(prefs::kStabilityLaunchedActivityFlags, launched); + } + + pref->CommitPendingWrite(); +} + +// static +void MetricsService::DiscardOldStabilityStatsAndroid(PrefService* local_state) { + local_state->SetInteger(prefs::kStabilityForegroundActivityType, + ActivityTypeIds::ACTIVITY_NONE); + local_state->SetInteger(prefs::kStabilityLaunchedActivityFlags, 0); + + ListPrefUpdate launches(local_state, prefs::kStabilityLaunchedActivityCounts); + launches.Get()->Clear(); + + ListPrefUpdate crashes(local_state, prefs::kStabilityCrashedActivityCounts); + crashes.Get()->Clear(); +} diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index b3ea39d..1900034 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -981,6 +981,7 @@ 'target_name': 'chrome_java', 'type': 'none', 'dependencies': [ + 'activity_type_ids_java', 'chrome_resources.gyp:chrome_strings', 'profile_sync_service_model_type_selection_java', 'resource_id_java', diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 8743fd0..7fd948e 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -100,6 +100,9 @@ 'browser/accessibility/accessibility_events.h', 'browser/accessibility/invert_bubble_prefs.cc', 'browser/accessibility/invert_bubble_prefs.h', + 'browser/android/activity_type_id_list.h', + 'browser/android/activity_type_ids.cc', + 'browser/android/activity_type_ids.h', 'browser/android/banners/app_banner_settings_helper.cc', 'browser/android/banners/app_banner_settings_helper.h', 'browser/android/bookmarks/managed_bookmarks_shim.cc', @@ -1234,6 +1237,7 @@ 'browser/metrics/metrics_network_observer.h', 'browser/metrics/metrics_reporting_scheduler.cc', 'browser/metrics/metrics_reporting_scheduler.h', + 'browser/metrics/metrics_service_android.cc', 'browser/metrics/metrics_service.cc', 'browser/metrics/metrics_service.h', 'browser/metrics/perf_provider_chromeos.cc', @@ -3719,6 +3723,18 @@ 'includes': [ '../build/jni_generator.gypi' ], }, { + 'target_name': 'activity_type_ids_java', + 'type': 'none', + 'sources': [ + 'android/java/ActivityTypeIds.template', + ], + 'variables': { + 'package_name': 'org/chromium/chrome/browser', + 'template_deps': ['browser/android/activity_type_id_list.h'], + }, + 'includes': [ '../build/android/java_cpp_template.gypi' ], + }, + { 'target_name': 'resource_id_java', 'type': 'none', 'sources': [ diff --git a/chrome/common/metrics/metrics_service_base.cc b/chrome/common/metrics/metrics_service_base.cc index 5f4edc2..66e8238 100644 --- a/chrome/common/metrics/metrics_service_base.cc +++ b/chrome/common/metrics/metrics_service_base.cc @@ -26,7 +26,14 @@ const char MetricsServiceBase::kMimeType[] = "application/vnd.chrome.uma"; void MetricsServiceBase::RecordCurrentHistograms() { DCHECK(log_manager_.current_log()); - histogram_snapshot_manager_.PrepareDeltas(base::Histogram::kNoFlags, true); + histogram_snapshot_manager_.PrepareDeltas( + base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag); +} + +void MetricsServiceBase::RecordCurrentStabilityHistograms() { + DCHECK(log_manager_.current_log()); + histogram_snapshot_manager_.PrepareDeltas( + base::Histogram::kNoFlags, base::Histogram::kUmaStabilityHistogramFlag); } void MetricsServiceBase::RecordDelta( diff --git a/chrome/common/metrics/metrics_service_base.h b/chrome/common/metrics/metrics_service_base.h index 24e73e7..f3a4a67 100644 --- a/chrome/common/metrics/metrics_service_base.h +++ b/chrome/common/metrics/metrics_service_base.h @@ -43,6 +43,10 @@ class MetricsServiceBase : public base::HistogramFlattener { // Called when we close a log. void RecordCurrentHistograms(); + // Record complete list of stability histograms into the current log, + // i.e., histograms with the |kUmaStabilityHistogramFlag| flag set. + void RecordCurrentStabilityHistograms(); + // Manager for the various in-flight logs. MetricsLogManager log_manager_; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index dc7ee69..baad881 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1505,6 +1505,29 @@ const char kStabilityKernelCrashCount[] = const char kStabilitySystemUncleanShutdownCount[] = "user_experience_metrics.stability.system_unclean_shutdowns"; +#if defined(OS_ANDROID) +// Activity type that is currently in the foreground for the UMA session. +// Uses the ActivityTypeIds::Type enum. +const char kStabilityForegroundActivityType[] = + "user_experience_metrics.stability.current_foreground_activity_type"; + +// Tracks which Activities were launched during the last session. +// See |metrics_service_android.cc| for its usage. +const char kStabilityLaunchedActivityFlags[] = + "user_experience_metrics.stability.launched_activity_flags"; + +// List pref: Counts how many times each Activity was launched. +// Indexed into by ActivityTypeIds::Type. +const char kStabilityLaunchedActivityCounts[] = + "user_experience_metrics.stability.launched_activity_counts"; + +// List pref: Counts how many times each Activity type was in the foreground +// when a UMA session failed to be shut down properly. +// Indexed into by ActivityTypeIds::Type. +const char kStabilityCrashedActivityCounts[] = + "user_experience_metrics.stability.crashed_activity_counts"; +#endif + // Number of times the browser has been able to register crash reporting. const char kStabilityBreakpadRegistrationSuccess[] = "user_experience_metrics.stability.breakpad_registration_ok"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 8c3e946..c069f1d 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -477,6 +477,12 @@ extern const char kStabilityChildProcessCrashCount[]; extern const char kStabilityOtherUserCrashCount[]; extern const char kStabilityKernelCrashCount[]; extern const char kStabilitySystemUncleanShutdownCount[]; +#if defined(OS_ANDROID) +extern const char kStabilityForegroundActivityType[]; +extern const char kStabilityLaunchedActivityFlags[]; +extern const char kStabilityLaunchedActivityCounts[]; +extern const char kStabilityCrashedActivityCounts[]; +#endif extern const char kStabilityBreakpadRegistrationSuccess[]; extern const char kStabilityBreakpadRegistrationFail[]; diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 977e434..eb1eab2 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -1436,6 +1436,22 @@ other types of suffix sets. </summary> </histogram> +<histogram name="Chrome.Android.Activity.CrashCounts" enum="AndroidActivityId"> + <summary> + Indicates how many times each particular type of Activity was in the + foreground when a UMA session was terminated abnormally. UMA sessions last + as long as Chrome remains in the foreground. + </summary> +</histogram> + +<histogram name="Chrome.Android.Activity.LaunchCounts" enum="AndroidActivityId"> + <summary> + Indicates how many times each particular type of Activity was brought to the + foreground when a UMA session was active (i.e. launched at some point). UMA + sessions last as long as Chrome remains in the foreground. + </summary> +</histogram> + <histogram name="Chrome.Browser.CrashedExecutionPhase" enum="ExecutionPhase"> <summary> Indicates the execution phase the browser was in when the browser crashed. @@ -22547,6 +22563,14 @@ other types of suffix sets. <int value="4" label="Snapped"/> </enum> +<enum name="AndroidActivityId" type="int"> + <int value="1" label="Unknown"/> + <int value="2" label="Main"/> + <int value="3" label="Preferences"/> + <int value="4" label="WebappActivity"/> + <int value="5" label="FullScreenActivity"/> +</enum> + <enum name="AndroidEvictionReason" type="int"> <int value="0" label="TabUnusedTooLong"/> <int value="1" label="TabUnusedInSession"/> |