// 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 static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; import static android.content.ComponentCallbacks2.TRIM_MEMORY_COMPLETE; import static android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE; import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; import static android.content.ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; import android.os.SystemClock; import org.chromium.base.metrics.RecordHistogram; import java.util.concurrent.TimeUnit; /** * Centralizes UMA data collection for Android-specific memory conditions. */ public class MemoryUma { // AndroidMemoryNotificationBackground defined in tools/metrics/histograms/histograms.xml. private static final int BACKGROUND_TRIM_UI_HIDDEN = 0; private static final int BACKGROUND_TRIM_BACKGROUND = 1; private static final int BACKGROUND_TRIM_MODERATE = 2; private static final int BACKGROUND_TRIM_COMPLETE = 3; private static final int BACKGROUND_MAX = 4; // AndroidMemoryNotificationForeground defined in tools/metrics/histograms/histograms.xml. private static final int FOREGROUND_TRIM_MODERATE = 0; private static final int FOREGROUND_TRIM_LOW = 1; private static final int FOREGROUND_TRIM_CRITICAL = 2; private static final int FOREGROUND_LOW = 3; private static final int FOREGROUND_MAX = 4; // Timestamp of the last time we received a LowMemory call since Chrome is in foreground. private long mLastLowMemoryMsec = -1; public void onStop() { mLastLowMemoryMsec = -1; } public void onLowMemory() { memoryNotificationForeground(FOREGROUND_LOW); long now = SystemClock.elapsedRealtime(); if (mLastLowMemoryMsec >= 0) { RecordHistogram.recordCustomTimesHistogram("MemoryAndroid.LowMemoryTimeBetween", now - mLastLowMemoryMsec, 0, TimeUnit.MINUTES.toMillis(10), TimeUnit.MILLISECONDS, 50); } mLastLowMemoryMsec = now; } public void onTrimMemory(int level) { if (level >= TRIM_MEMORY_COMPLETE) { memoryNotificationBackground(BACKGROUND_TRIM_COMPLETE); } else if (level >= TRIM_MEMORY_MODERATE) { memoryNotificationBackground(BACKGROUND_TRIM_MODERATE); } else if (level >= TRIM_MEMORY_BACKGROUND) { memoryNotificationBackground(BACKGROUND_TRIM_BACKGROUND); } else if (level >= TRIM_MEMORY_UI_HIDDEN) { memoryNotificationBackground(BACKGROUND_TRIM_UI_HIDDEN); } else if (level >= TRIM_MEMORY_RUNNING_CRITICAL) { memoryNotificationForeground(FOREGROUND_TRIM_CRITICAL); } else if (level >= TRIM_MEMORY_RUNNING_LOW) { memoryNotificationForeground(FOREGROUND_TRIM_LOW); } else if (level >= TRIM_MEMORY_RUNNING_MODERATE) { memoryNotificationForeground(FOREGROUND_TRIM_MODERATE); } } private static void memoryNotificationForeground(int notification) { assert notification >= 0 && notification < FOREGROUND_MAX; RecordHistogram.recordEnumeratedHistogram("MemoryAndroid.NotificationForeground", notification, FOREGROUND_MAX); } private static void memoryNotificationBackground(int notification) { assert notification >= 0 && notification < BACKGROUND_MAX; RecordHistogram.recordEnumeratedHistogram("MemoryAndroid.NotificationBackground", notification, BACKGROUND_MAX); } }