blob: e8b91f39877727629089e0f4d9c9fcfdd07d752a [file] [log] [blame]
// Copyright 2017 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.download;
import static android.app.DownloadManager.ACTION_NOTIFICATION_CLICKED;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_CANCEL;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_OPEN;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_PAUSE;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_RESUME;
import android.support.annotation.IntDef;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.metrics.RecordHistogram;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
/**
* Helper to track necessary stats in UMA related to downloads notifications.
*/
public final class DownloadNotificationUmaHelper {
// The state of a download or offline page request at user-initiated cancel.
// Keep in sync with enum OfflineItemsStateAtCancel in enums.xml.
@IntDef({StateAtCancel.DOWNLOADING, StateAtCancel.PAUSED, StateAtCancel.PENDING_NETWORK,
StateAtCancel.PENDING_ANOTHER_DOWNLOAD})
@Retention(RetentionPolicy.SOURCE)
public @interface StateAtCancel {
int DOWNLOADING = 0;
int PAUSED = 1;
int PENDING_NETWORK = 2;
int PENDING_ANOTHER_DOWNLOAD = 3;
int NUM_ENTRIES = 4;
}
// NOTE: Keep these lists/classes in sync with DownloadNotification[...] in enums.xml.
@IntDef({ForegroundLifecycle.START, ForegroundLifecycle.UPDATE, ForegroundLifecycle.STOP})
@Retention(RetentionPolicy.SOURCE)
public @interface ForegroundLifecycle {
int START = 0; // Initial startForeground.
int UPDATE = 1; // Switching pinned notification.
int STOP = 2; // Calling stopForeground.
int NUM_ENTRIES = 3;
}
private static List<String> sInteractions = Arrays.asList(
ACTION_NOTIFICATION_CLICKED, // Opening a download where LegacyHelpers.isLegacyDownload.
ACTION_DOWNLOAD_OPEN, // Opening a download that is not a legacy download.
ACTION_DOWNLOAD_CANCEL, ACTION_DOWNLOAD_PAUSE, ACTION_DOWNLOAD_RESUME);
@IntDef({LaunchType.LAUNCH, LaunchType.RELAUNCH})
@Retention(RetentionPolicy.SOURCE)
public @interface LaunchType {
int LAUNCH = 0; // "Denominator" for expected launched notifications.
int RELAUNCH = 1;
int NUM_ENTRIES = 2;
}
@IntDef({ServiceStopped.STOPPED, ServiceStopped.DESTROYED, ServiceStopped.TASK_REMOVED,
ServiceStopped.LOW_MEMORY, ServiceStopped.START_STICKY})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceStopped {
int STOPPED = 0; // Expected, intentional stops, serves as a "denominator".
int DESTROYED = 1;
int TASK_REMOVED = 2;
int LOW_MEMORY = 3;
int START_STICKY = 4;
int NUM_ENTRIES = 5;
}
// Values for the histogram MobileDownloadResumptionCount.
@IntDef({UmaDownloadResumption.MANUAL_PAUSE, UmaDownloadResumption.BROWSER_KILLED,
UmaDownloadResumption.CLICKED, UmaDownloadResumption.FAILED,
UmaDownloadResumption.AUTO_STARTED, UmaDownloadResumption.BROWSER_RUNNING,
UmaDownloadResumption.BROWSER_NOT_RUNNING})
@Retention(RetentionPolicy.SOURCE)
public @interface UmaDownloadResumption {
int MANUAL_PAUSE = 0;
int BROWSER_KILLED = 1;
int CLICKED = 2;
int FAILED = 3;
int AUTO_STARTED = 4;
int BROWSER_RUNNING = 5;
int BROWSER_NOT_RUNNING = 6;
int NUM_ENTRIES = 7;
}
// Values for the histograms MobileDownload.Background.*. Keep in sync with
// MobileDownloadBackgroundDownloadEvent in enums.xml.
@IntDef({UmaBackgroundDownload.STARTED, UmaBackgroundDownload.COMPLETED,
UmaBackgroundDownload.CANCELLED, UmaBackgroundDownload.FAILED,
UmaBackgroundDownload.INTERRUPTED})
@Retention(RetentionPolicy.SOURCE)
public @interface UmaBackgroundDownload {
int STARTED = 0;
int COMPLETED = 1;
int CANCELLED = 2;
int FAILED = 3;
int INTERRUPTED = 4;
int NUM_ENTRIES = 5;
}
/**
* Records an instance where a user interacts with a notification (clicks on, pauses, etc).
* @param action Notification interaction that was taken (ie. pause, resume).
*/
static void recordNotificationInteractionHistogram(String action) {
if (!LibraryLoader.getInstance().isInitialized()) return;
int actionType = sInteractions.indexOf(action);
if (actionType == -1) return;
RecordHistogram.recordEnumeratedHistogram("Android.DownloadManager.NotificationInteraction",
actionType, sInteractions.size());
}
/**
* Records an instance where the foreground stops, using expected stops as the denominator to
* understand the frequency of unexpected stops (low memory, task removed, etc).
* @param stopType Type of the foreground stop that is being recorded ({@link ServiceStopped}).
*/
static void recordServiceStoppedHistogram(
@ServiceStopped int stopType, boolean withForeground) {
if (!LibraryLoader.getInstance().isInitialized()) return;
if (withForeground) {
RecordHistogram.recordEnumeratedHistogram(
"Android.DownloadManager.ServiceStopped.DownloadForeground", stopType,
ServiceStopped.NUM_ENTRIES);
} else {
RecordHistogram.recordEnumeratedHistogram(
"Android.DownloadManager.ServiceStopped.DownloadNotification", stopType,
ServiceStopped.NUM_ENTRIES);
}
}
/**
* Records an instance where the foreground undergoes a lifecycle change (when the foreground
* starts, changes pinned notification, or stops).
* @param lifecycleStep The lifecycle step that is being recorded ({@link ForegroundLifecycle}).
*/
static void recordForegroundServiceLifecycleHistogram(@ForegroundLifecycle int lifecycleStep) {
if (!LibraryLoader.getInstance().isInitialized()) return;
RecordHistogram.recordEnumeratedHistogram(
"Android.DownloadManager.ForegroundServiceLifecycle", lifecycleStep,
ForegroundLifecycle.NUM_ENTRIES);
}
/**
* Record the number of existing notifications when a new notification is being launched (more
* specifically the number of existing shared preference entries when a new shared preference
* entry is being recorded).
* @param count The number of existing notifications.
* @param withForeground Whether this is with foreground enabled or not.
*/
static void recordExistingNotificationsCountHistogram(int count, boolean withForeground) {
if (!LibraryLoader.getInstance().isInitialized()) return;
if (withForeground) {
RecordHistogram.recordCountHistogram(
"Android.DownloadManager.NotificationsCount.ForegroundEnabled", count);
} else {
RecordHistogram.recordCountHistogram(
"Android.DownloadManager.NotificationsCount.ForegroundDisabled", count);
}
}
/**
* Record an instance when a notification is being launched for the first time or relaunched due
* to the need to dissociate the notification from the foreground (only on API < 24).
* @param launchType Whether it is a launch or a relaunch ({@link LaunchType}).
*/
static void recordNotificationFlickerCountHistogram(@LaunchType int launchType) {
if (!LibraryLoader.getInstance().isInitialized()) return;
RecordHistogram.recordEnumeratedHistogram(
"Android.DownloadManager.NotificationLaunch", launchType, LaunchType.NUM_ENTRIES);
}
/**
* Records the state of a request at user-initiated cancel.
* @param isDownload True if the request is a download, false if it is an offline page.
* @param state State of a request when cancelled (e.g. downloading, paused).
*/
static void recordStateAtCancelHistogram(boolean isDownload, @StateAtCancel int state) {
if (state == -1) return;
if (!LibraryLoader.getInstance().isInitialized()) return;
if (isDownload) {
RecordHistogram.recordEnumeratedHistogram(
"Android.OfflineItems.StateAtCancel.Downloads", state,
StateAtCancel.NUM_ENTRIES);
} else {
RecordHistogram.recordEnumeratedHistogram(
"Android.OfflineItems.StateAtCancel.OfflinePages", state,
StateAtCancel.NUM_ENTRIES);
}
}
/**
* Helper method to record the download resumption UMA.
* @param type UMA type to be recorded.
*/
static void recordDownloadResumptionHistogram(@UmaDownloadResumption int type) {
RecordHistogram.recordEnumeratedHistogram(
"MobileDownload.DownloadResumption", type, UmaDownloadResumption.NUM_ENTRIES);
}
/**
* Helper method to record the background download resumption UMA.
* @param type UMA type to be recorded.
*/
static void recordBackgroundDownloadHistogram(@UmaBackgroundDownload int type) {
RecordHistogram.recordEnumeratedHistogram(
"MobileDownload.Background", type, UmaBackgroundDownload.NUM_ENTRIES);
}
/**
* Helper method to record the first background download resumption UMA.
* @param type UMA type to be recorded.
*/
static void recordFirstBackgroundDownloadHistogram(@UmaBackgroundDownload int type) {
RecordHistogram.recordEnumeratedHistogram(
"MobileDownload.Background.FirstDownload", type, UmaBackgroundDownload.NUM_ENTRIES);
}
}