michael@0: /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko; michael@0: michael@0: import org.mozilla.gecko.mozglue.RobocopTarget; michael@0: michael@0: import android.os.SystemClock; michael@0: import android.util.Log; michael@0: michael@0: /** michael@0: * All telemetry times are relative to one of two clocks: michael@0: * michael@0: * * Real time since the device was booted, including deep sleep. Use this michael@0: * as a substitute for wall clock. michael@0: * * Uptime since the device was booted, excluding deep sleep. Use this to michael@0: * avoid timing a user activity when their phone is in their pocket! michael@0: * michael@0: * The majority of methods in this class are defined in terms of real time. michael@0: */ michael@0: @RobocopTarget michael@0: public class Telemetry { michael@0: private static final String LOGTAG = "Telemetry"; michael@0: michael@0: public static long uptime() { michael@0: return SystemClock.uptimeMillis(); michael@0: } michael@0: michael@0: public static long realtime() { michael@0: return SystemClock.elapsedRealtime(); michael@0: } michael@0: michael@0: // Define new histograms in: michael@0: // toolkit/components/telemetry/Histograms.json michael@0: public static void HistogramAdd(String name, int value) { michael@0: GeckoEvent event = GeckoEvent.createTelemetryHistogramAddEvent(name, value); michael@0: GeckoAppShell.sendEventToGecko(event); michael@0: } michael@0: michael@0: public abstract static class Timer { michael@0: private final long mStartTime; michael@0: private final String mName; michael@0: michael@0: private volatile boolean mHasFinished = false; michael@0: private volatile long mElapsed = -1; michael@0: michael@0: protected abstract long now(); michael@0: michael@0: public Timer(String name) { michael@0: mName = name; michael@0: mStartTime = now(); michael@0: } michael@0: michael@0: public void cancel() { michael@0: mHasFinished = true; michael@0: } michael@0: michael@0: public long getElapsed() { michael@0: return mElapsed; michael@0: } michael@0: michael@0: public void stop() { michael@0: // Only the first stop counts. michael@0: if (mHasFinished) { michael@0: return; michael@0: } michael@0: michael@0: mHasFinished = true; michael@0: michael@0: final long elapsed = now() - mStartTime; michael@0: if (elapsed < 0) { michael@0: Log.e(LOGTAG, "Current time less than start time -- clock shenanigans?"); michael@0: return; michael@0: } michael@0: michael@0: mElapsed = elapsed; michael@0: if (elapsed > Integer.MAX_VALUE) { michael@0: Log.e(LOGTAG, "Duration of " + elapsed + "ms is too great to add to histogram."); michael@0: return; michael@0: } michael@0: michael@0: HistogramAdd(mName, (int)(elapsed)); michael@0: } michael@0: } michael@0: michael@0: public static class RealtimeTimer extends Timer { michael@0: public RealtimeTimer(String name) { michael@0: super(name); michael@0: } michael@0: michael@0: @Override michael@0: protected long now() { michael@0: return Telemetry.realtime(); michael@0: } michael@0: } michael@0: michael@0: public static class UptimeTimer extends Timer { michael@0: public UptimeTimer(String name) { michael@0: super(name); michael@0: } michael@0: michael@0: @Override michael@0: protected long now() { michael@0: return Telemetry.uptime(); michael@0: } michael@0: } michael@0: michael@0: public static void startUISession(String sessionName) { michael@0: Log.d(LOGTAG, "StartUISession: " + sessionName); michael@0: GeckoEvent event = GeckoEvent.createTelemetryUISessionStartEvent(sessionName, realtime()); michael@0: GeckoAppShell.sendEventToGecko(event); michael@0: } michael@0: michael@0: public static void stopUISession(String sessionName, String reason) { michael@0: Log.d(LOGTAG, "StopUISession: " + sessionName + ", reason=" + reason); michael@0: GeckoEvent event = GeckoEvent.createTelemetryUISessionStopEvent(sessionName, reason, realtime()); michael@0: GeckoAppShell.sendEventToGecko(event); michael@0: } michael@0: michael@0: public static void stopUISession(String sessionName) { michael@0: stopUISession(sessionName, null); michael@0: } michael@0: michael@0: public static void sendUIEvent(String action, String method, long timestamp, String extras) { michael@0: Log.d(LOGTAG, "SendUIEvent: action = " + action + " method = " + method + " timestamp = " + timestamp + " extras = " + extras); michael@0: GeckoEvent event = GeckoEvent.createTelemetryUIEvent(action, method, timestamp, extras); michael@0: GeckoAppShell.sendEventToGecko(event); michael@0: } michael@0: michael@0: public static void sendUIEvent(String action, String method, long timestamp) { michael@0: sendUIEvent(action, method, timestamp, null); michael@0: } michael@0: michael@0: public static void sendUIEvent(String action, String method, String extras) { michael@0: sendUIEvent(action, method, realtime(), extras); michael@0: } michael@0: michael@0: public static void sendUIEvent(String action, String method) { michael@0: sendUIEvent(action, method, realtime(), null); michael@0: } michael@0: michael@0: public static void sendUIEvent(String action) { michael@0: sendUIEvent(action, null, realtime(), null); michael@0: } michael@0: }