Commit 5b7dfc1c authored by Dan Harrington's avatar Dan Harrington Committed by Commit Bot

android: track background UMA sessions

Added a new histogram 'Session.Background.TotalDuration'. This is recorded
in every log which contains a background session.

When the UMABackgroundSessions feature is enabled, we also attempt to open
new UMA logs on foreground/background transitions to segment
foreground/background UMA.

The primary goal is to learn which whether any given UMA histogram is
being reported in the foreground, or the background.

Bug: 954310
Change-Id: I7cb5bdbdc9d153e32bc283065f8147d548a82f45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1650526Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarHenrique Nakashima <hnakashima@chromium.org>
Reviewed-by: default avatarCarlos Knippschild <carlosk@chromium.org>
Commit-Queue: Dan H <harringtond@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689081}
parent 65459217
...@@ -225,6 +225,7 @@ chrome_test_java_sources = [ ...@@ -225,6 +225,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java", "javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java",
"javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java", "javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java",
"javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java",
"javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java", "javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java",
"javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java", "javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java",
"javatests/src/org/chromium/chrome/browser/metrics/UkmTest.java", "javatests/src/org/chromium/chrome/browser/metrics/UkmTest.java",
......
...@@ -9,6 +9,8 @@ import android.content.Context; ...@@ -9,6 +9,8 @@ import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.text.TextUtils; import android.text.TextUtils;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
...@@ -225,6 +227,14 @@ public class UmaSessionStats { ...@@ -225,6 +227,14 @@ public class UmaSessionStats {
.isFullBrowserStarted(); .isFullBrowserStarted();
} }
/**
* Returns whether there is a visible activity.
*/
@CalledByNative
private static boolean hasVisibleActivity() {
return ApplicationStatus.hasVisibleActivities();
}
private static native long nativeInit(); private static native long nativeInit();
private static native void nativeChangeMetricsReportingConsent(boolean consent); private static native void nativeChangeMetricsReportingConsent(boolean consent);
private static native void nativeInitMetricsAndCrashReportingForTesting(); private static native void nativeInitMetricsAndCrashReportingForTesting();
......
// Copyright 2019 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.metrics;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.uiautomator.UiDevice;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.PostTask;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.init.BrowserParts;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.init.EmptyBrowserParts;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Tests relating to UMA reported while Chrome is backgrounded.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.
Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-enable-metrics-reporting"})
public final class BackgroundMetricsTest {
// Note: these rules might conflict and so calls to their methods must be handled carefully.
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Before
public void setUp() {}
private void waitForHistogram(String name, int count) throws Throwable {
CriteriaHelper.pollUiThread(() -> {
return RecordHistogram.getHistogramTotalCountForTesting(name) >= count;
}, "waitForHistogram timeout", 10000, 200);
}
public void pressHome() throws Throwable {
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.pressHome();
}
private void loadNative() {
final AtomicBoolean mNativeLoaded = new AtomicBoolean();
final BrowserParts parts = new EmptyBrowserParts() {
@Override
public void finishNativeInitialization() {
mNativeLoaded.set(true);
}
};
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
try {
ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts);
ChromeBrowserInitializer.getInstance().handlePostNativeStartup(true, parts);
} catch (ProcessInitException e) {
ChromeApplication.reportStartupErrorAndExit(e);
}
});
CriteriaHelper.pollUiThread(
() -> mNativeLoaded.get(), "Failed while waiting for starting native.");
}
@Test
@MediumTest
@CommandLineFlags.Add({"disable-features=UMABackgroundSessions"})
public void testBackgroundSessionIsRecordedWithBackgroundSessionsDisabled() throws Throwable {
// Start Chrome.
mActivityTestRule.startMainActivityOnBlankPage();
// Background Chrome and wait for a session to be recorded.
pressHome();
waitForHistogram("Session.TotalDuration", 1);
Assert.assertEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Session.Background.TotalDuration"));
// Foreground Chrome, and verify a background session is recorded.
mActivityTestRule.startMainActivityOnBlankPage();
waitForHistogram("Session.Background.TotalDuration", 1);
}
@Test
@MediumTest
@CommandLineFlags.Add({"enable-features=UMABackgroundSessions"})
public void testBackgroundSessionIsRecordedWithBackgroundSessionsEnabled() throws Throwable {
// Start Chrome.
mActivityTestRule.startMainActivityOnBlankPage();
// Background Chrome and wait for a session to be recorded.
pressHome();
waitForHistogram("Session.TotalDuration", 1);
Assert.assertEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Session.Background.TotalDuration"));
// Foreground Chrome, and verify a background session is recorded.
mActivityTestRule.startMainActivityOnBlankPage();
waitForHistogram("Session.Background.TotalDuration", 1);
// UMABackgroundSessions triggers additional UMA logs to be written, but there's currently
// not a good way to test this because it requires waiting a significant amount of time
// for some initialization to occur in metrics_service.cc.
}
@Test
@MediumTest
@CommandLineFlags.Add({"enable-features=UMABackgroundSessions"})
public void testStartInBackgroundRecordsBackgroundSession() throws Throwable {
// Start native, without an activity.
loadNative();
Assert.assertEquals(0,
RecordHistogram.getHistogramTotalCountForTesting(
"Session.Background.TotalDuration"));
// Start an activity and verify the background session was recorded.
mActivityTestRule.startMainActivityOnBlankPage();
waitForHistogram("Session.Background.TotalDuration", 1);
}
}
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -36,31 +37,42 @@ using base::android::JavaParamRef; ...@@ -36,31 +37,42 @@ using base::android::JavaParamRef;
using base::UserMetricsAction; using base::UserMetricsAction;
namespace { namespace {
UmaSessionStats* g_uma_session_stats = NULL;
// Used to keep the state of whether we should consider metric consent enabled. // Used to keep the state of whether we should consider metric consent enabled.
// This is used/read only within the ChromeMetricsServiceAccessor methods. // This is used/read only within the ChromeMetricsServiceAccessor methods.
bool g_metrics_consent_for_testing = false; bool g_metrics_consent_for_testing = false;
} // namespace } // namespace
UmaSessionStats::UmaSessionStats() UmaSessionStats::UmaSessionStats() = default;
: active_session_count_(0) { UmaSessionStats::~UmaSessionStats() = default;
}
UmaSessionStats::~UmaSessionStats() { // static
UmaSessionStats* UmaSessionStats::GetInstance() {
static base::NoDestructor<UmaSessionStats> instance;
return instance.get();
} }
void UmaSessionStats::UmaResumeSession(JNIEnv* env, void UmaSessionStats::UmaResumeSession(JNIEnv* env,
const JavaParamRef<jobject>& obj) { const JavaParamRef<jobject>& obj) {
DCHECK(g_browser_process); DCHECK(g_browser_process);
if (++active_session_count_ == 1) {
if (active_session_count_ == 0) { const bool had_background_session =
session_start_time_ = base::TimeTicks::Now(); session_time_tracker_.BeginForegroundSession();
// Tell the metrics services that the application resumes. // Tell the metrics services that the application resumes.
metrics::MetricsService* metrics = g_browser_process->metrics_service(); metrics::MetricsService* metrics = g_browser_process->metrics_service();
if (metrics) if (metrics) {
metrics->OnAppEnterForeground(); // Forcing a new log allows foreground and background metrics can be
// separated in analysis.
const bool force_new_log = base::FeatureList::IsEnabled(
chrome::android::kUmaBackgroundSessions) &&
had_background_session;
metrics->OnAppEnterForeground(force_new_log);
}
// Report background session time if it wasn't already reported by
// OnAppEnterForeground() -> ProvideCurrentSessionData().
session_time_tracker_.ReportBackgroundSessionTime();
ukm::UkmService* ukm_service = ukm::UkmService* ukm_service =
g_browser_process->GetMetricsServicesManager()->GetUkmService(); g_browser_process->GetMetricsServicesManager()->GetUkmService();
if (ukm_service) if (ukm_service)
...@@ -68,10 +80,11 @@ void UmaSessionStats::UmaResumeSession(JNIEnv* env, ...@@ -68,10 +80,11 @@ void UmaSessionStats::UmaResumeSession(JNIEnv* env,
AndroidProfileSessionDurationsService* psd_service = AndroidProfileSessionDurationsService* psd_service =
AndroidProfileSessionDurationsServiceFactory::GetForActiveUserProfile(); AndroidProfileSessionDurationsServiceFactory::GetForActiveUserProfile();
if (psd_service) if (psd_service) {
psd_service->OnAppEnterForeground(session_start_time_); psd_service->OnAppEnterForeground(
session_time_tracker_.session_start_time());
}
} }
++active_session_count_;
} }
void UmaSessionStats::UmaEndSession(JNIEnv* env, void UmaSessionStats::UmaEndSession(JNIEnv* env,
...@@ -80,14 +93,8 @@ void UmaSessionStats::UmaEndSession(JNIEnv* env, ...@@ -80,14 +93,8 @@ void UmaSessionStats::UmaEndSession(JNIEnv* env,
DCHECK_GE(active_session_count_, 0); DCHECK_GE(active_session_count_, 0);
if (active_session_count_ == 0) { if (active_session_count_ == 0) {
base::TimeDelta duration = base::TimeTicks::Now() - session_start_time_; const base::TimeDelta duration =
session_time_tracker_.EndForegroundSession();
// Note: This metric is recorded separately on desktop in
// DesktopSessionDurationTracker::EndSession.
UMA_HISTOGRAM_LONG_TIMES("Session.TotalDuration", duration);
UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDurationMax1Day", duration,
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromHours(24), 50);
DCHECK(g_browser_process); DCHECK(g_browser_process);
// Tell the metrics services they were cleanly shutdown. // Tell the metrics services they were cleanly shutdown.
...@@ -106,9 +113,73 @@ void UmaSessionStats::UmaEndSession(JNIEnv* env, ...@@ -106,9 +113,73 @@ void UmaSessionStats::UmaEndSession(JNIEnv* env,
AndroidProfileSessionDurationsServiceFactory::GetForActiveUserProfile(); AndroidProfileSessionDurationsServiceFactory::GetForActiveUserProfile();
if (psd_service) if (psd_service)
psd_service->OnAppEnterBackground(duration); psd_service->OnAppEnterBackground(duration);
// Note: Keep the line below after |metrics->OnAppEnterBackground()|.
// Otherwise, |ProvideCurrentSessionData()| may report a small timeslice of
// background session time toward the previous log.
session_time_tracker_.BeginBackgroundSession();
}
}
// Called on startup. If there is an activity, do nothing because a foreground
// session will be created naturally. Otherwise, begin recording a background
// session.
void UmaSessionStats::OnStartup() {
if (!Java_UmaSessionStats_hasVisibleActivity(
base::android::AttachCurrentThread())) {
GetInstance()->session_time_tracker_.BeginBackgroundSession();
} }
} }
bool UmaSessionStats::SessionTimeTracker::BeginForegroundSession() {
AccumulateBackgroundSessionTime();
background_session_start_time_ = {};
session_start_time_ = base::TimeTicks::Now();
return !background_session_accumulated_time_.is_zero();
}
void UmaSessionStats::SessionTimeTracker::AccumulateBackgroundSessionTime() {
// No time spent in background since the last call to
// |AccumulateBackgroundSessionTime()|.
if (background_session_start_time_.is_null())
return;
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta duration = now - background_session_start_time_;
background_session_accumulated_time_ += duration;
background_session_start_time_ = now;
}
void UmaSessionStats::SessionTimeTracker::ReportBackgroundSessionTime() {
if (background_session_accumulated_time_.is_zero())
return;
// This histogram is used in analysis to determine if an uploaded log
// represents background activity. For this reason, this histogram may be
// recorded more than once per 'background session'.
UMA_HISTOGRAM_CUSTOM_TIMES(
"Session.Background.TotalDuration", background_session_accumulated_time_,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(24), 50);
background_session_accumulated_time_ = base::TimeDelta();
}
base::TimeDelta UmaSessionStats::SessionTimeTracker::EndForegroundSession() {
base::TimeDelta duration = base::TimeTicks::Now() - session_start_time_;
// Note: This metric is recorded separately on desktop in
// DesktopSessionDurationTracker::EndSession.
UMA_HISTOGRAM_LONG_TIMES("Session.TotalDuration", duration);
UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDurationMax1Day", duration,
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromHours(24), 50);
return duration;
}
void UmaSessionStats::SessionTimeTracker::BeginBackgroundSession() {
background_session_start_time_ = base::TimeTicks::Now();
}
// static // static
void UmaSessionStats::RegisterSyntheticFieldTrial( void UmaSessionStats::RegisterSyntheticFieldTrial(
const std::string& trial_name, const std::string& trial_name,
...@@ -125,6 +196,13 @@ void UmaSessionStats::RegisterSyntheticMultiGroupFieldTrial( ...@@ -125,6 +196,13 @@ void UmaSessionStats::RegisterSyntheticMultiGroupFieldTrial(
trial_name, group_name_hashes); trial_name, group_name_hashes);
} }
void UmaSessionStats::ProvideCurrentSessionData() {
// We record Session.Background.TotalDuration here to ensure each UMA log
// containing a background session contains this histogram.
session_time_tracker_.AccumulateBackgroundSessionTime();
session_time_tracker_.ReportBackgroundSessionTime();
}
// Updates metrics reporting state managed by native code. This should only be // Updates metrics reporting state managed by native code. This should only be
// called when consent is changing, and UpdateMetricsServiceState() should be // called when consent is changing, and UpdateMetricsServiceState() should be
// called immediately after for metrics services to be started or stopped as // called immediately after for metrics services to be started or stopped as
...@@ -268,7 +346,5 @@ static void JNI_UmaSessionStats_RecordPageLoadedWithKeyboard(JNIEnv*) { ...@@ -268,7 +346,5 @@ static void JNI_UmaSessionStats_RecordPageLoadedWithKeyboard(JNIEnv*) {
static jlong JNI_UmaSessionStats_Init(JNIEnv* env) { static jlong JNI_UmaSessionStats_Init(JNIEnv* env) {
// We should have only one UmaSessionStats instance. // We should have only one UmaSessionStats instance.
DCHECK(!g_uma_session_stats); return reinterpret_cast<intptr_t>(UmaSessionStats::GetInstance());
g_uma_session_stats = new UmaSessionStats();
return reinterpret_cast<intptr_t>(g_uma_session_stats);
} }
...@@ -14,18 +14,25 @@ ...@@ -14,18 +14,25 @@
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h"
#include "base/time/time.h" #include "base/time/time.h"
// The native part of java UmaSessionStats class. // The native part of java UmaSessionStats class. This is a singleton.
class UmaSessionStats { class UmaSessionStats {
public: public:
UmaSessionStats(); static UmaSessionStats* GetInstance();
void UmaResumeSession(JNIEnv* env, void UmaResumeSession(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
void UmaEndSession(JNIEnv* env, void UmaEndSession(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
// Called before an UMA log is completed to record associated metrics.
void ProvideCurrentSessionData();
// Called once on browser startup.
static void OnStartup();
static void RegisterSyntheticFieldTrial(const std::string& trial_name, static void RegisterSyntheticFieldTrial(const std::string& trial_name,
const std::string& group_name); const std::string& group_name);
...@@ -34,11 +41,44 @@ class UmaSessionStats { ...@@ -34,11 +41,44 @@ class UmaSessionStats {
const std::vector<uint32_t>& group_name_hashes); const std::vector<uint32_t>& group_name_hashes);
private: private:
friend class base::NoDestructor<UmaSessionStats>;
UmaSessionStats();
~UmaSessionStats(); ~UmaSessionStats();
// Start of the current session, used for UMA. class SessionTimeTracker {
base::TimeTicks session_start_time_; public:
int active_session_count_; SessionTimeTracker() = default;
SessionTimeTracker(const SessionTimeTracker&) = delete;
SessionTimeTracker& operator=(const SessionTimeTracker&) = delete;
// Adds time to |background_session_start_time_| if a background session is
// currently active.
void AccumulateBackgroundSessionTime();
// Reports accumulated background session time, if any exists.
void ReportBackgroundSessionTime();
// Ends any background session, and begins a new foreground session timer.
// Returns whether a background session was terminated by this foreground
// session.
bool BeginForegroundSession();
// Marks the end of a foreground session and returns its duration.
base::TimeDelta EndForegroundSession();
// Begins a new background session timer.
void BeginBackgroundSession();
base::TimeTicks session_start_time() const { return session_start_time_; }
private:
// Start of the current session.
base::TimeTicks session_start_time_;
// Start of the current background session. Null if there is no active
// background session.
base::TimeTicks background_session_start_time_;
// Total accumulated and unreported background session time.
base::TimeDelta background_session_accumulated_time_;
};
SessionTimeTracker session_time_tracker_;
int active_session_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(UmaSessionStats); DISALLOW_COPY_AND_ASSIGN(UmaSessionStats);
}; };
......
...@@ -196,6 +196,7 @@ ...@@ -196,6 +196,7 @@
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/chrome_feature_list.h"
#include "chrome/browser/android/metrics/uma_session_stats.h"
#include "chrome/browser/metrics/thread_watcher_android.h" #include "chrome/browser/metrics/thread_watcher_android.h"
#include "ui/base/resource/resource_bundle_android.h" #include "ui/base/resource/resource_bundle_android.h"
#else #else
...@@ -683,9 +684,20 @@ void ChromeBrowserMainParts::SetupMetrics() { ...@@ -683,9 +684,20 @@ void ChromeBrowserMainParts::SetupMetrics() {
->RegisterSyntheticTrials(); ->RegisterSyntheticTrials();
} }
// static
void ChromeBrowserMainParts::StartMetricsRecording() { void ChromeBrowserMainParts::StartMetricsRecording() {
TRACE_EVENT0("startup", "ChromeBrowserMainParts::StartMetricsRecording"); TRACE_EVENT0("startup", "ChromeBrowserMainParts::StartMetricsRecording");
#if defined(OS_ANDROID)
UmaSessionStats::OnStartup();
// Android updates the metrics service dynamically depending on whether the
// application is in the foreground or not. Do not start here unless
// kUmaBackgroundSessions is enabled.
if (!base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions))
return;
#endif
g_browser_process->metrics_service()->CheckForClonedInstall(); g_browser_process->metrics_service()->CheckForClonedInstall();
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -1306,18 +1318,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { ...@@ -1306,18 +1318,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
IncognitoModePrefs::InitializePlatformParentalControls(); IncognitoModePrefs::InitializePlatformParentalControls();
#endif #endif
// Android updates the metrics service dynamically depending on whether the // Now that the file thread has been started, start metrics.
// application is in the foreground or not. Do not start here.
#if !defined(OS_ANDROID)
// Now that the file thread has been started, start recording.
StartMetricsRecording(); StartMetricsRecording();
#else
// When kUmaBackgroundSessions is enabled, start metrics recording for every
// Chrome start. Otherwise, recording is only started when Chrome becomes
// foregrounded.
if (base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions))
StartMetricsRecording();
#endif // !defined(OS_ANDROID)
if (!base::debug::BeingDebugged()) { if (!base::debug::BeingDebugged()) {
// Create watchdog thread after creating all other threads because it will // Create watchdog thread after creating all other threads because it will
......
...@@ -100,7 +100,7 @@ class ChromeBrowserMainParts : public content::BrowserMainParts { ...@@ -100,7 +100,7 @@ class ChromeBrowserMainParts : public content::BrowserMainParts {
// Starts recording of metrics. This can only be called after we have a file // Starts recording of metrics. This can only be called after we have a file
// thread. // thread.
void StartMetricsRecording(); static void StartMetricsRecording();
// Record time from process startup to present time in an UMA histogram. // Record time from process startup to present time in an UMA histogram.
void RecordBrowserStartupTime(); void RecordBrowserStartupTime();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/system/sys_info.h" #include "base/system/sys_info.h"
#include "chrome/browser/android/feature_utilities.h" #include "chrome/browser/android/feature_utilities.h"
#include "chrome/browser/android/locale/locale_manager.h" #include "chrome/browser/android/locale/locale_manager.h"
#include "chrome/browser/android/metrics/uma_session_stats.h"
namespace { namespace {
...@@ -55,6 +56,7 @@ void AndroidMetricsProvider::ProvideCurrentSessionData( ...@@ -55,6 +56,7 @@ void AndroidMetricsProvider::ProvideCurrentSessionData(
UMA_HISTOGRAM_BOOLEAN( UMA_HISTOGRAM_BOOLEAN(
"Android.MultiWindowMode.Active", "Android.MultiWindowMode.Active",
chrome::android::GetIsInMultiWindowModeValue()); chrome::android::GetIsInMultiWindowModeValue());
UmaSessionStats::GetInstance()->ProvideCurrentSessionData();
EmitAppNotificationStatusHistogram(); EmitAppNotificationStatusHistogram();
LocaleManager::RecordUserTypeMetrics(); LocaleManager::RecordUserTypeMetrics();
} }
...@@ -416,10 +416,18 @@ void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) { ...@@ -416,10 +416,18 @@ void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
} }
} }
void MetricsService::OnAppEnterForeground() { void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
state_manager_->clean_exit_beacon()->WriteBeaconValue(false); state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
StartSchedulerIfNecessary(); StartSchedulerIfNecessary();
if (force_open_new_log && recording_active() && state_ >= SENDING_LOGS) {
// Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage()
// will close the log, allowing a new log to be opened.
PushPendingLogsToPersistentStorage();
OpenNewLog();
}
} }
#else #else
void MetricsService::LogNeedForCleanShutdown() { void MetricsService::LogNeedForCleanShutdown() {
state_manager_->clean_exit_beacon()->WriteBeaconValue(false); state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
......
...@@ -134,7 +134,7 @@ class MetricsService : public base::HistogramFlattener { ...@@ -134,7 +134,7 @@ class MetricsService : public base::HistogramFlattener {
void OnAppEnterBackground(bool keep_recording_in_background = false); void OnAppEnterBackground(bool keep_recording_in_background = false);
// Called when the application is coming out of background mode. // Called when the application is coming out of background mode.
void OnAppEnterForeground(); void OnAppEnterForeground(bool force_open_new_log = false);
#else #else
// Set the dirty flag, which will require a later call to LogCleanShutdown(). // Set the dirty flag, which will require a later call to LogCleanShutdown().
void LogNeedForCleanShutdown(); void LogNeedForCleanShutdown();
......
...@@ -125663,6 +125663,20 @@ should be kept until we remove incident reporting. --> ...@@ -125663,6 +125663,20 @@ should be kept until we remove incident reporting. -->
</summary> </summary>
</histogram> </histogram>
<histogram name="Session.Background.TotalDuration" units="ms"
expires_after="2020-07-01">
<owner>harringtond@chromium.org</owner>
<owner>asvitkine@chromium.org</owner>
<summary>
Sum of this metric yields the total time Chrome was running in the
background. A single session may be represented by multiple values, so that
this histogram is always present in an uploaded log that represents
background activity.
Android-only.
</summary>
</histogram>
<histogram name="Session.ClosedTabCounts" units="operations"> <histogram name="Session.ClosedTabCounts" units="operations">
<owner>rohitrao@chromium.org</owner> <owner>rohitrao@chromium.org</owner>
<summary> <summary>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment