Index: chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3de19bafbc1a31750bf2c62603582c5c2c929b4 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java |
@@ -0,0 +1,189 @@ |
+// Copyright 2015 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.app.Activity; |
+import android.content.ComponentCallbacks; |
+import android.content.Context; |
+import android.content.res.Configuration; |
+ |
+import org.chromium.base.ActivityState; |
+import org.chromium.base.ApplicationStatus; |
+import org.chromium.chrome.browser.Tab; |
+import org.chromium.chrome.browser.preferences.privacy.CrashReportingPermissionManager; |
+import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager; |
+import org.chromium.chrome.browser.tabmodel.TabModel; |
+import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; |
+import org.chromium.content_public.browser.WebContents; |
+import org.chromium.net.NetworkChangeNotifier; |
+ |
+/** |
+ * Mainly sets up session stats for chrome. A session is defined as the duration when the |
+ * application is in the foreground. Also used to communicate information between Chrome |
+ * and the framework's MetricService. |
+ */ |
+public class UmaSessionStats implements NetworkChangeNotifier.ConnectionTypeObserver { |
+ private static final String SAMSUNG_MULTWINDOW_PACKAGE = "com.sec.feature.multiwindow"; |
+ |
+ private static long sNativeUmaSessionStats = 0; |
+ |
+ // TabModelSelector is needed to get the count of open tabs. We want to log the number of open |
+ // tabs on every page load. |
+ private TabModelSelector mTabModelSelector; |
+ private TabModelSelectorTabObserver mTabModelSelectorTabObserver; |
+ |
+ private final Context mContext; |
+ private final boolean mIsMultiWindowCapable; |
+ private ComponentCallbacks mComponentCallbacks; |
+ |
+ private boolean mKeyboardConnected = false; |
+ private final CrashReportingPermissionManager mReportingPermissionManager; |
+ |
+ public UmaSessionStats(Context context) { |
+ mContext = context; |
+ mIsMultiWindowCapable = context.getPackageManager().hasSystemFeature( |
+ SAMSUNG_MULTWINDOW_PACKAGE); |
+ mReportingPermissionManager = PrivacyPreferencesManager.getInstance(context); |
+ } |
+ |
+ private void recordPageLoadStats(int tabId) { |
+ Tab tab = mTabModelSelector.getTabById(tabId); |
+ if (tab == null) return; |
+ WebContents webContents = tab.getWebContents(); |
+ boolean isDesktopUserAgent = webContents != null |
+ && webContents.getNavigationController().getUseDesktopUserAgent(); |
+ nativeRecordPageLoaded(isDesktopUserAgent); |
+ if (mKeyboardConnected) { |
+ nativeRecordPageLoadedWithKeyboard(); |
+ } |
+ |
+ TabModel regularModel = mTabModelSelector.getModel(false); |
+ nativeRecordTabCountPerLoad(getTabCountFromModel(regularModel)); |
+ } |
+ |
+ private int getTabCountFromModel(TabModel model) { |
+ return model == null ? 0 : model.getCount(); |
+ } |
+ |
+ /** |
+ * Starts a new session for logging. |
+ * @param tabModelSelector A TabModelSelector instance for recording tab counts on page loads. |
+ * If null, UmaSessionStats does not record page loads and tab counts. |
+ */ |
+ public void startNewSession(TabModelSelector tabModelSelector) { |
+ ensureNativeInitialized(); |
+ |
+ mTabModelSelector = tabModelSelector; |
+ if (mTabModelSelector != null) { |
+ mComponentCallbacks = new ComponentCallbacks() { |
+ @Override |
+ public void onLowMemory() { |
+ // Not required |
+ } |
+ |
+ @Override |
+ public void onConfigurationChanged(Configuration newConfig) { |
+ mKeyboardConnected = newConfig.keyboard != Configuration.KEYBOARD_NOKEYS; |
+ } |
+ }; |
+ mContext.registerComponentCallbacks(mComponentCallbacks); |
+ mKeyboardConnected = mContext.getResources().getConfiguration() |
+ .keyboard != Configuration.KEYBOARD_NOKEYS; |
+ mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) { |
+ @Override |
+ public void onPageLoadFinished(Tab tab) { |
+ recordPageLoadStats(tab.getId()); |
+ } |
+ }; |
+ } |
+ |
+ nativeUmaResumeSession(sNativeUmaSessionStats); |
+ NetworkChangeNotifier.addConnectionTypeObserver(this); |
+ updateMetricsServiceState(); |
+ } |
+ |
+ private static void ensureNativeInitialized() { |
+ // Lazily create the native object and the notification handler. These objects are never |
+ // destroyed. |
+ if (sNativeUmaSessionStats == 0) { |
+ sNativeUmaSessionStats = nativeInit(); |
+ } |
+ } |
+ |
+ /** |
+ * Logs screen ratio on Samsung MultiWindow devices. |
+ */ |
+ public void logMultiWindowStats(int windowArea, int displayArea, int instanceCount) { |
+ if (mIsMultiWindowCapable) { |
+ if (displayArea == 0) return; |
+ int areaPercent = (windowArea * 100) / displayArea; |
+ int safePercent = areaPercent > 0 ? areaPercent : 0; |
+ nativeRecordMultiWindowSession(safePercent, instanceCount); |
+ } |
+ } |
+ |
+ /** |
+ * Logs the current session. |
+ */ |
+ public void logAndEndSession() { |
+ if (mTabModelSelector != null) { |
+ mContext.unregisterComponentCallbacks(mComponentCallbacks); |
+ mTabModelSelectorTabObserver.destroy(); |
+ mTabModelSelector = null; |
+ } |
+ |
+ nativeUmaEndSession(sNativeUmaSessionStats); |
+ NetworkChangeNotifier.removeConnectionTypeObserver(this); |
+ } |
+ |
+ public static void logRendererCrash(Activity activity) { |
+ int activityState = ApplicationStatus.getStateForActivity(activity); |
+ nativeLogRendererCrash( |
+ activityState == ActivityState.PAUSED |
+ || activityState == ActivityState.STOPPED |
+ || activityState == ActivityState.DESTROYED); |
+ } |
+ |
+ /** |
+ * Updates the state of the MetricsService to account for the user's preferences. |
+ */ |
+ public void updateMetricsServiceState() { |
+ boolean mayRecordStats = !PrivacyPreferencesManager.getInstance(mContext) |
+ .isNeverUploadCrashDump(); |
+ boolean mayUploadStats = mReportingPermissionManager.isUploadPermitted(); |
+ |
+ // Re-start the MetricsService with the given parameters. |
+ nativeUpdateMetricsServiceState(mayRecordStats, mayUploadStats); |
+ } |
+ |
+ @Override |
+ public void onConnectionTypeChanged(int connectionType) { |
+ updateMetricsServiceState(); |
+ } |
+ |
+ public static void registerExternalExperiment(int studyId, int experimentId) { |
+ nativeRegisterExternalExperiment(studyId, experimentId); |
+ } |
+ |
+ public static void registerSyntheticFieldTrial(String trialName, String groupName) { |
+ nativeRegisterSyntheticFieldTrial(trialName, groupName); |
+ } |
+ |
+ private static native long nativeInit(); |
+ private native void nativeUpdateMetricsServiceState(boolean mayRecord, boolean mayUpload); |
+ private native void nativeUmaResumeSession(long nativeUmaSessionStats); |
+ private native void nativeUmaEndSession(long nativeUmaSessionStats); |
+ private static native void nativeLogRendererCrash(boolean isPaused); |
+ private static native void nativeRegisterExternalExperiment(int studyId, |
+ int experimentId); |
+ private static native void nativeRegisterSyntheticFieldTrial( |
+ String trialName, String groupName); |
+ private static native void nativeRecordMultiWindowSession(int areaPercent, int instanceCount); |
+ private static native void nativeRecordTabCountPerLoad(int numTabsOpen); |
+ private static native void nativeRecordPageLoaded(boolean isDesktopUserAgent); |
+ private static native void nativeRecordPageLoadedWithKeyboard(); |
+ |
+} |